1 Data Import and Cleaning

# import data
data_path <- "../data/preprocessed/omnibus/omnibus_bl_corrected_pickups.csv"

all_data <- fread(data_path)

## Setup ##
palette <- dict(
  list(
    "s30" = "#a30f15",
    "d30" = "#07509b",
    "s30-a" = "#fb6949",
    "d30-a" = "#6aafd2",
    "a-1" = "#4f1b31",
    "a-2" = "#d6819b"
  )
)

## Isolate experiments and summarize ##
sr_30_all <- all_data %>%
  filter(exp == "sr_30") %>%
  mutate(unsigned_obj_angle = obj_angle_3cm_move * obj_shape_sign * -1) %>%
  mutate(unsigned_hand_angle = hand_angle_3cm_move * obj_shape_sign * -1)

sr_30_ppt_training <- sr_30_all %>%
  filter(block_num == 16) %>%
  mutate(trial_set = case_when(
    trial_num <= 141 ~ 1,
    trial_num >= 310 ~ 2,
    TRUE ~ 100
  ))

sr_30_clamped <- sr_30_all %>%
  filter(block_num > 16, type == "clamped") %>%
  mutate(trained_obj_factor = case_when(
    trainedfirst_obj_shape == obj_shape ~ "trained_obj",
    TRUE ~ "untrained_obj"
  )) %>%
  mutate(trained_hand_factor = case_when(
    hand == "r" ~ "trained_hand",
    TRUE ~ "untrained_hand"
  )) %>%
  mutate(trained_obj_hand_factor = paste0(trained_obj_factor, "_", trained_hand_factor))

### DR 30 ###
dr_30_all <- all_data %>%
  filter(exp == "dr_30") %>%
  mutate(unsigned_obj_angle = obj_angle_3cm_move * obj_shape_sign * -1) %>%
  mutate(unsigned_hand_angle = hand_angle_3cm_move * obj_shape_sign * -1)

dr_30_ppt_training <- dr_30_all %>%
  filter(block_num == 7) %>%
  mutate(trial_set = case_when(
    trial_num <= 78 ~ 1,
    trial_num >= 247 ~ 2,
    TRUE ~ 100
  ))

# note: blocks 8 and 11 are include clamps, 13 is exclude clamps
dr_30_incl_clamp <- dr_30_all %>%
  filter(block_num %in% c(8, 11))

dr_30_excl_clamp <- dr_30_all %>%
  filter(block_num %in% c(13, 14))

# both experiment rbind
both_ppt_training <- rbind(sr_30_ppt_training, dr_30_ppt_training)

2 Dual Learning Diffs

2.1 Including Strategy

dr_30_ppt_incl_clamped <- dr_30_incl_clamp %>%
  group_by(ppid, obj_shape_sign) %>%
  summarise(
    ppt_mean_angle = mean(obj_angle_3cm_move),
    ppt_ci_angle = vector_confint(obj_angle_3cm_move)
  )
`summarise()` has grouped output by 'ppid'. You can override using the `.groups` argument.
dr_30_ppt_incl_clamped$obj_shape_sign <- factor(
  dr_30_ppt_incl_clamped$obj_shape_sign
)

dr_30_exp_incl_clamped <- dr_30_ppt_incl_clamped %>%
  group_by(obj_shape_sign) %>%
  summarise(
    mean_angle = mean(ppt_mean_angle),
    ci_angle = vector_confint(ppt_mean_angle)
  )

# add a difference column
dr_30_ppt_incl_clamped <- dr_30_ppt_incl_clamped %>%
  group_by(ppid) %>%
  mutate(
    diff = ppt_mean_angle - lag(ppt_mean_angle)
  )

# plot the trial sets
p <- dr_30_ppt_incl_clamped %>%
  ggplot(
    aes(
      x = obj_shape_sign, y = ppt_mean_angle,
      colour = ppid
    )
  ) +
  theme_classic() +
  theme(legend.position = "none") +
  labs(
    x = "Trial Set",
    y = "Hand Angle (°)"
  ) +
  geom_point() +
  geom_line(aes(group = ppid), alpha = 0.2)

ggplotly(p)

# plot the diffs
p <- dr_30_ppt_incl_clamped %>%
  filter(obj_shape_sign == 1) %>%
  ggplot(
    aes(
      x = obj_shape_sign,
      colour = ppid
    )
  ) +
  theme_classic() +
  theme(legend.position = "none") +
  geom_hline(
    yintercept = c(0), linewidth = 0.4,
    colour = "#CCCCCC", linetype = "dashed"
  ) +
  # add data
  geom_beeswarm(
    aes(
      y = diff
    ),
    alpha = 0.5,
    size = 1
  )

ggplotly(p)

Removing ppt “dr_30_2”

data_ppt <- dr_30_ppt_incl_clamped %>%
  filter(ppid != "dr_30_2")

# summary statistics
data_ppt %>% 
  group_by(obj_shape_sign) %>% 
  summarise(
    mean = mean(ppt_mean_angle),
    ci = vector_confint(ppt_mean_angle),
    n = n()
  )
# Comparison stats
# paired t-test
group1 <- data_ppt %>% 
  filter(obj_shape_sign == "-1") %>% 
  pull(ppt_mean_angle)

group2 <- data_ppt %>%
  filter(obj_shape_sign == "1") %>% 
  pull(ppt_mean_angle)

diffs <- group2 - group1
t.test(diffs)

    One Sample t-test

data:  diffs
t = -4.2632, df = 28, p-value = 0.0002067
alternative hypothesis: true mean is not equal to 0
95 percent confidence interval:
 -4.756845 -1.669237
sample estimates:
mean of x 
-3.213041 
# Effect size
cohen.d(group1, group2)

Cohen's d

d estimate: 0.5720102 (medium)
95 percent confidence interval:
     lower      upper 
0.03528311 1.10873733 
# Bayes factor
ttestBF(x = diffs)
Bayes factor analysis
--------------
[1] Alt., r=0.707 : 135.9736 ±0%

Against denominator:
  Null, mu = 0 
---
Bayes factor type: BFoneSample, JZS

2.2 Excluding strategy

dr_30_ppt_excl_clamped <- dr_30_excl_clamp %>%
  group_by(ppid, obj_shape_sign) %>%
  summarise(
    ppt_mean_angle = mean(obj_angle_3cm_move),
    ppt_ci_angle = vector_confint(obj_angle_3cm_move)
  )
`summarise()` has grouped output by 'ppid'. You can override using the `.groups` argument.
dr_30_ppt_excl_clamped$obj_shape_sign <- factor(
  dr_30_ppt_excl_clamped$obj_shape_sign
)

dr_30_exp_excl_clamped <- dr_30_ppt_excl_clamped %>%
  group_by(obj_shape_sign) %>%
  summarise(
    mean_angle = mean(ppt_mean_angle),
    ci_angle = vector_confint(ppt_mean_angle)
  )

# add a difference column
dr_30_ppt_excl_clamped <- dr_30_ppt_excl_clamped %>%
  group_by(ppid) %>%
  mutate(
    diff = ppt_mean_angle - lag(ppt_mean_angle)
  )

# plot the trial sets
p <- dr_30_ppt_excl_clamped %>%
  ggplot(
    aes(
      x = obj_shape_sign, y = ppt_mean_angle,
      colour = ppid
    )
  ) +
  theme_classic() +
  theme(legend.position = "none") +
  labs(
    x = "Trial Set",
    y = "Hand Angle (°)"
  ) +
  geom_point() +
  geom_line(aes(group = ppid), alpha = 0.2)

ggplotly(p)

# plot the diffs
p <- dr_30_ppt_excl_clamped %>%
  filter(obj_shape_sign == 1) %>%
  ggplot(
    aes(
      x = obj_shape_sign,
      colour = ppid
    )
  ) +
  theme_classic() +
  theme(legend.position = "none") +
  geom_hline(
    yintercept = c(0), linewidth = 0.4,
    colour = "#CCCCCC", linetype = "dashed"
  ) +
  # add data
  geom_beeswarm(
    aes(
      y = diff
    ),
    alpha = 0.5,
    size = 1
  )

ggplotly(p)

Removing ppt “dr_30_2”

data_ppt <- dr_30_ppt_excl_clamped %>%
  filter(ppid != "dr_30_2")

# summary statistics
data_ppt %>% 
  group_by(obj_shape_sign) %>% 
  summarise(
    mean = mean(ppt_mean_angle),
    ci = vector_confint(ppt_mean_angle),
    n = n()
  )
# Comparison stats
# paired t-test
group1 <- data_ppt %>% 
  filter(obj_shape_sign == "-1") %>% 
  pull(ppt_mean_angle)

group2 <- data_ppt %>%
  filter(obj_shape_sign == "1") %>% 
  pull(ppt_mean_angle)

diffs <- group2 - group1
t.test(diffs)

    One Sample t-test

data:  diffs
t = -1.8713, df = 28, p-value = 0.07178
alternative hypothesis: true mean is not equal to 0
95 percent confidence interval:
 -6.3401315  0.2864248
sample estimates:
mean of x 
-3.026853 
# Effect size
cohen.d(group1, group2)

Cohen's d

d estimate: 0.4200617 (small)
95 percent confidence interval:
     lower      upper 
-0.1117851  0.9519085 
# Bayes factor
ttestBF(x = diffs)
Bayes factor analysis
--------------
[1] Alt., r=0.707 : 0.9124751 ±0.02%

Against denominator:
  Null, mu = 0 
---
Bayes factor type: BFoneSample, JZS

3 Single Learning

3.1 Training Phase Trial Sets - Reach Step

sr_30_ppt_trial_sets <- sr_30_ppt_training %>%
  filter(trial_set < 5) %>%
  group_by(ppid, trial_set, targetAngle) %>%
  summarise(
    mean_trial_set_angle = mean(unsigned_hand_angle),
    n()
  )
`summarise()` has grouped output by 'ppid', 'trial_set'. You can override using the `.groups` argument.
sr_30_ppt_trial_sets$ppid <- as.factor(sr_30_ppt_trial_sets$ppid)
sr_30_ppt_trial_sets$trial_set <- as.factor(sr_30_ppt_trial_sets$trial_set)
sr_30_ppt_trial_sets$targetAngle <- as.factor(sr_30_ppt_trial_sets$targetAngle)

sr_30_trial_set_devs <- sr_30_ppt_trial_sets %>%
  group_by(trial_set, targetAngle) %>%
  summarise(
    trial_set_mean = mean(mean_trial_set_angle),
    trial_set_ci = vector_confint(mean_trial_set_angle)
  )
`summarise()` has grouped output by 'trial_set'. You can override using the `.groups` argument.
data_ppt <- sr_30_ppt_trial_sets
data_trial_set <- sr_30_trial_set_devs

# set up plot
p <- data_trial_set %>%
  ggplot(
    aes(
      x = trial_set, y = trial_set_mean
    )
  ) +
  theme_classic() +
  theme(legend.position = "none") +
  labs(
    x = NULL,
    y = "Hand Angle (°)"
  )

# add horizontal lines
p <- p +
  geom_hline(
    yintercept = c(0, 30), linewidth = 0.4,
    colour = "#CCCCCC", linetype = "solid"
  ) +
  geom_hline(
    yintercept = c(15), linewidth = 0.4,
    colour = "#CCCCCC", linetype = "dashed"
  )

# add axis ticks
p <- p +
  scale_y_continuous(
    limits = c(-15, 40),
    breaks = c(0, 15, 30),
    labels = c(0, 15, 30)
  )

# set font size to 11
p <- p +
  theme(text = element_text(size = 11))

# add data points
p <- p +
  geom_beeswarm(
    data = data_ppt,
    aes(y = mean_trial_set_angle, colour = targetAngle),
    alpha = 0.5,
    size = 1
  ) +
  geom_linerange(aes(
    ymin = trial_set_mean - trial_set_ci,
    ymax = trial_set_mean + trial_set_ci
  ), alpha = 0.1, lwd = 2) +
  geom_point()

# p <- p +
#   scale_color_manual(
#     values = c(
#       "#555555", "#555555"
#     )
#   )

p <- p +
  scale_x_discrete(
    labels = c(
      "Init\nT", "Fin\nT"
    )
  )

p

# ANOVA using afex (identical values to ez but ez doesn't remove missing rows)
(temp_ANOVA <- aov_car(mean_trial_set_angle ~ targetAngle * trial_set + Error(ppid / (targetAngle * trial_set)), data_ppt))
Anova Table (Type 3 tests)

Response: mean_trial_set_angle
                 Effect          df    MSE    F   ges p.value
1           targetAngle 1.97, 61.06  44.75 0.06 <.001    .943
2             trial_set       1, 31 132.95 0.71  .006    .406
3 targetAngle:trial_set 1.97, 61.19  36.62 1.40  .006    .253
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘+’ 0.1 ‘ ’ 1

Sphericity correction method: GG 
bf <- anovaBF(mean_trial_set_angle ~ targetAngle * trial_set + ppid,
  data = data.frame(data_ppt), whichRandom = "ppid", progress = FALSE
)
print(bf)
Bayes factor analysis
--------------
[1] trial_set + ppid                                       : 0.32554     ±1.18%
[2] targetAngle + ppid                                     : 0.05606566  ±1.36%
[3] trial_set + targetAngle + ppid                         : 0.01790458  ±1.27%
[4] trial_set + targetAngle + trial_set:targetAngle + ppid : 0.003506085 ±2.12%

Against denominator:
  mean_trial_set_angle ~ ppid 
---
Bayes factor type: BFlinearModel, JZS
bayesfactor_inclusion(bf)
Inclusion Bayes Factors (Model Averaged)

                      P(prior) P(posterior) Inclusion BF
ppid                      1.00         1.00             
trial_set                 0.60         0.25        0.219
targetAngle               0.60         0.06        0.039
targetAngle:trial_set     0.20     2.50e-03        0.010

* Compared among: all models
*    Priors odds: uniform-equal

3.2 Training Phase Trial Sets - Transport Step

sr_30_ppt_trial_sets <- sr_30_ppt_training %>%
  filter(trial_set < 5) %>%
  group_by(ppid, trial_set, targetAngle) %>%
  summarise(
    mean_trial_set_angle = mean(unsigned_obj_angle)
  )
`summarise()` has grouped output by 'ppid', 'trial_set'. You can override using the `.groups` argument.
sr_30_ppt_trial_sets$ppid <- as.factor(sr_30_ppt_trial_sets$ppid)
sr_30_ppt_trial_sets$trial_set <- as.factor(sr_30_ppt_trial_sets$trial_set)
sr_30_ppt_trial_sets$targetAngle <- as.factor(sr_30_ppt_trial_sets$targetAngle)

sr_30_trial_set_devs <- sr_30_ppt_trial_sets %>%
  group_by(trial_set, targetAngle) %>%
  summarise(
    trial_set_mean = mean(mean_trial_set_angle),
    trial_set_ci = vector_confint(mean_trial_set_angle)
  )
`summarise()` has grouped output by 'trial_set'. You can override using the `.groups` argument.
data_ppt <- sr_30_ppt_trial_sets
data_trial_set <- sr_30_trial_set_devs

# set up plot
p <- data_trial_set %>%
  ggplot(
    aes(
      x = trial_set, y = trial_set_mean
    )
  ) +
  theme_classic() +
  theme(legend.position = "none") +
  labs(
    x = NULL,
    y = NULL
  )

# add horizontal lines
p <- p +
  geom_hline(
    yintercept = c(0, 30), linewidth = 0.4,
    colour = "#CCCCCC", linetype = "solid"
  ) +
  geom_hline(
    yintercept = c(15), linewidth = 0.4,
    colour = "#CCCCCC", linetype = "dashed"
  )

# add axis ticks
p <- p +
  scale_y_continuous(
    limits = c(-15, 40),
    breaks = c(0, 15, 30),
    labels = c(0, 15, 30)
  )

# set font size to 11
p <- p +
  theme(text = element_text(size = 11))

# add data points
p <- p +
  geom_beeswarm(
    data = data_ppt,
    aes(y = mean_trial_set_angle, colour = targetAngle),
    alpha = 0.5,
    size = 1
  ) +
  geom_linerange(aes(
    ymin = trial_set_mean - trial_set_ci,
    ymax = trial_set_mean + trial_set_ci
  ), alpha = 0.1, lwd = 2) +
  geom_point()

# p <- p +
#   scale_color_manual(
#     values = c(
#       palette$get("s30"), palette$get("s30")
#     )
#   )

p <- p +
  scale_x_discrete(
    labels = c(
      "Init\nT", "Fin\nT"
    )
  )

p

# ANOVA using afex (identical values to ez but ez doesn't remove missing rows)
(temp_ANOVA <- aov_car(mean_trial_set_angle ~ targetAngle * trial_set + Error(ppid / (targetAngle * trial_set)), data_ppt))
Anova Table (Type 3 tests)

Response: mean_trial_set_angle
                 Effect          df    MSE         F   ges p.value
1           targetAngle 1.71, 52.97 438.07      0.02 <.001    .962
2             trial_set       1, 31 593.64 40.52 ***  .158   <.001
3 targetAngle:trial_set 1.77, 54.89 411.66      0.23  .001    .765
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘+’ 0.1 ‘ ’ 1

Sphericity correction method: GG 
bf <- anovaBF(mean_trial_set_angle ~ targetAngle * trial_set + ppid,
  data = data.frame(data_ppt), whichRandom = "ppid", progress = FALSE
)
print(bf)
Bayes factor analysis
--------------
[1] trial_set + ppid                                       : 5473262810 ±0.99%
[2] targetAngle + ppid                                     : 0.05464965 ±1.08%
[3] trial_set + targetAngle + ppid                         : 305702870  ±4.01%
[4] trial_set + targetAngle + trial_set:targetAngle + ppid : 32635998   ±1.64%

Against denominator:
  mean_trial_set_angle ~ ppid 
---
Bayes factor type: BFlinearModel, JZS
bayesfactor_inclusion(bf)
Inclusion Bayes Factors (Model Averaged)

                      P(prior) P(posterior) Inclusion BF
ppid                      1.00         1.00             
trial_set                 0.60         1.00     3.67e+09
targetAngle               0.60         0.06        0.041
targetAngle:trial_set     0.20     5.62e-03        0.023

* Compared among: all models
*    Priors odds: uniform-equal

No effects of target Angle (BFincl of 0.04 and 0.08)

4 Dual Learning Experiment

4.1 Training Phase Trial Sets - Reach Step

dr_30_ppt_trial_sets <- dr_30_ppt_training %>%
  filter(trial_set < 5) %>%
  group_by(ppid, trial_set, targetAngle) %>%
  summarise(
    mean_trial_set_angle = mean(unsigned_hand_angle)
  )
`summarise()` has grouped output by 'ppid', 'trial_set'. You can override using the `.groups` argument.
dr_30_ppt_trial_sets$ppid <- as.factor(dr_30_ppt_trial_sets$ppid)
dr_30_ppt_trial_sets$trial_set <- as.factor(dr_30_ppt_trial_sets$trial_set)
dr_30_ppt_trial_sets$targetAngle <- as.factor(dr_30_ppt_trial_sets$targetAngle)

dr_30_trial_set_devs <- dr_30_ppt_trial_sets %>%
  group_by(trial_set, targetAngle) %>%
  summarise(
    trial_set_mean = mean(mean_trial_set_angle),
    trial_set_ci = vector_confint(mean_trial_set_angle)
  )
`summarise()` has grouped output by 'trial_set'. You can override using the `.groups` argument.
data_ppt <- dr_30_ppt_trial_sets
data_trial_set <- dr_30_trial_set_devs

# set up plot
p <- data_trial_set %>%
  ggplot(
    aes(
      x = trial_set, y = trial_set_mean,
      color = trial_set
    )
  ) +
  theme_classic() +
  theme(legend.position = "none") +
  labs(
    x = NULL,
    y = "Hand Angle (°)"
  )

# add horizontal lines
p <- p +
  geom_hline(
    yintercept = c(-30, 0, 30), linewidth = 0.4,
    colour = "#CCCCCC", linetype = "solid"
  ) +
  geom_hline(
    yintercept = c(-15, 15), linewidth = 0.4,
    colour = "#CCCCCC", linetype = "dashed"
  )

# add axis ticks
p <- p +
  scale_y_continuous(
    limits = c(-30, 30),
    breaks = c(-30, -15, 0, 15, 30),
    labels = c(-30, -15, 0, 15, 30)
  )

# set font size to 11
p <- p +
  theme(text = element_text(size = 11))

# add data points
p <- p +
  geom_beeswarm(
    data = data_ppt,
    aes(y = mean_trial_set_angle, colour = targetAngle),
    alpha = 0.5,
    size = 1
  ) +
  geom_linerange(aes(
    ymin = trial_set_mean - trial_set_ci,
    ymax = trial_set_mean + trial_set_ci
  ), alpha = 0.1, lwd = 2) +
  geom_point()

# p <- p +
#   scale_color_manual(
#     values = c(
#       "#555555", "#555555"
#     )
#   )

p <- p +
  scale_x_discrete(
    labels = c(
      "Init", "Fin"
    )
  )

p

# ANOVA using afex (identical values to ez but ez doesn't remove missing rows)
(temp_ANOVA <- aov_car(mean_trial_set_angle ~ targetAngle * trial_set + Error(ppid / (targetAngle * trial_set)), data_ppt))
Warning: Missing values for 1 ID(s), which were removed before analysis:
dr_30_22
Below the first few rows (in wide format) of the removed cases with missing data.
  
Anova Table (Type 3 tests)

Response: mean_trial_set_angle
                 Effect          df    MSE    F  ges p.value
1           targetAngle 1.29, 35.99 195.00 0.86 .006    .387
2             trial_set       1, 28 354.03 0.46 .005    .504
3 targetAngle:trial_set 1.26, 35.40 224.19 1.49 .012    .235
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘+’ 0.1 ‘ ’ 1

Sphericity correction method: GG 
bf <- anovaBF(mean_trial_set_angle ~ targetAngle * trial_set + ppid,
  data = data.frame(data_ppt), whichRandom = "ppid", progress = FALSE
)
print(bf)
Bayes factor analysis
--------------
[1] trial_set + ppid                                       : 0.253548    ±1.05%
[2] targetAngle + ppid                                     : 0.09704884  ±0.62%
[3] trial_set + targetAngle + ppid                         : 0.0255741   ±1.98%
[4] trial_set + targetAngle + trial_set:targetAngle + ppid : 0.006829371 ±1.95%

Against denominator:
  mean_trial_set_angle ~ ppid 
---
Bayes factor type: BFlinearModel, JZS
bayesfactor_inclusion(bf)
Inclusion Bayes Factors (Model Averaged)

                      P(prior) P(posterior) Inclusion BF
ppid                      1.00         1.00             
trial_set                 0.60         0.21        0.174
targetAngle               0.60         0.09        0.069
targetAngle:trial_set     0.20     4.94e-03        0.020

* Compared among: all models
*    Priors odds: uniform-equal

4.2 Training Phase Trial Sets - Transport Step

dr_30_ppt_trial_sets <- dr_30_ppt_training %>%
  filter(trial_set < 5) %>%
  group_by(ppid, trial_set, targetAngle) %>%
  summarise(
    mean_trial_set_angle = mean(unsigned_obj_angle)
  )
`summarise()` has grouped output by 'ppid', 'trial_set'. You can override using the `.groups` argument.
dr_30_ppt_trial_sets$ppid <- as.factor(dr_30_ppt_trial_sets$ppid)
dr_30_ppt_trial_sets$trial_set <- as.factor(dr_30_ppt_trial_sets$trial_set)
dr_30_ppt_trial_sets$targetAngle <- as.factor(dr_30_ppt_trial_sets$targetAngle)

dr_30_trial_set_devs <- dr_30_ppt_trial_sets %>%
  group_by(trial_set, targetAngle) %>%
  summarise(
    trial_set_mean = mean(mean_trial_set_angle),
    trial_set_ci = vector_confint(mean_trial_set_angle)
  )
`summarise()` has grouped output by 'trial_set'. You can override using the `.groups` argument.
data_ppt <- dr_30_ppt_trial_sets
data_trial_set <- dr_30_trial_set_devs

# set up plot
p <- data_trial_set %>%
  ggplot(
    aes(
      x = trial_set, y = trial_set_mean
    )
  ) +
  theme_classic() +
  theme(legend.position = "none") +
  labs(
    x = NULL,
    y = NULL
  )

# add horizontal lines
p <- p +
  geom_hline(
    yintercept = c(0, 30), linewidth = 0.4,
    colour = "#CCCCCC", linetype = "solid"
  ) +
  geom_hline(
    yintercept = c(15), linewidth = 0.4,
    colour = "#CCCCCC", linetype = "dashed"
  )

# add axis ticks
p <- p +
  scale_y_continuous(
    limits = c(-15, 40),
    breaks = c(0, 15, 30),
    labels = c(0, 15, 30)
  )

# set font size to 11
p <- p +
  theme(text = element_text(size = 11))

# add data points
p <- p +
  geom_beeswarm(
    data = data_ppt,
    aes(y = mean_trial_set_angle, colour = targetAngle),
    alpha = 0.5,
    size = 1
  ) +
  geom_linerange(aes(
    ymin = trial_set_mean - trial_set_ci,
    ymax = trial_set_mean + trial_set_ci
  ), alpha = 0.1, lwd = 2) +
  geom_point()

# p <- p +
#   scale_color_manual(
#     values = c(
#       palette$get("s30"), palette$get("s30")
#     )
#   )

p <- p +
  scale_x_discrete(
    labels = c(
      "Init\nT", "Fin\nT"
    )
  )

p

# ANOVA using afex (identical values to ez but ez doesn't remove missing rows)
(temp_ANOVA <- aov_car(mean_trial_set_angle ~ targetAngle * trial_set + Error(ppid / (targetAngle * trial_set)), data_ppt))
Warning: Missing values for 1 ID(s), which were removed before analysis:
dr_30_22
Below the first few rows (in wide format) of the removed cases with missing data.
  
Anova Table (Type 3 tests)

Response: mean_trial_set_angle
                 Effect          df   MSE      F  ges p.value
1           targetAngle 1.63, 45.61 47.71   1.80 .013    .182
2             trial_set       1, 28 88.82 4.00 + .034    .055
3 targetAngle:trial_set 1.42, 39.85 75.67   0.41 .004    .596
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘+’ 0.1 ‘ ’ 1

Sphericity correction method: GG 
bf <- anovaBF(mean_trial_set_angle ~ targetAngle * trial_set + ppid,
  data = data.frame(data_ppt), whichRandom = "ppid", progress = FALSE
)
print(bf)
Bayes factor analysis
--------------
[1] trial_set + ppid                                       : 2.838212  ±0.83%
[2] targetAngle + ppid                                     : 0.1859104 ±0.61%
[3] trial_set + targetAngle + ppid                         : 0.572867  ±1.7%
[4] trial_set + targetAngle + trial_set:targetAngle + ppid : 0.0780265 ±2.05%

Against denominator:
  mean_trial_set_angle ~ ppid 
---
Bayes factor type: BFlinearModel, JZS
bayesfactor_inclusion(bf)
Inclusion Bayes Factors (Model Averaged)

                      P(prior) P(posterior) Inclusion BF
ppid                      1.00         1.00             
trial_set                 0.60         0.75         1.96
targetAngle               0.60         0.18        0.145
targetAngle:trial_set     0.20         0.02        0.068

* Compared among: all models
*    Priors odds: uniform-equal

No effect of target angle (BFinc = 0.07, 0.14)

4.3 Clamped Tasks

4.3.1 Not excluding strategy

dr_30_ppt_incl_clamped <- dr_30_incl_clamp %>%
  group_by(ppid, obj_shape_sign, targetAngle) %>%
  summarise(
    ppt_mean_angle = mean(obj_angle_3cm_move),
    ppt_ci_angle = vector_confint(obj_angle_3cm_move)
  )
`summarise()` has grouped output by 'ppid', 'obj_shape_sign'. You can override using the `.groups` argument.
dr_30_ppt_incl_clamped$ppid <- factor(dr_30_ppt_incl_clamped$ppid)
dr_30_ppt_incl_clamped$obj_shape_sign <- factor(dr_30_ppt_incl_clamped$obj_shape_sign)
dr_30_ppt_incl_clamped$targetAngle <- factor(dr_30_ppt_incl_clamped$targetAngle)

dr_30_exp_incl_clamped <- dr_30_ppt_incl_clamped %>%
  group_by(obj_shape_sign, targetAngle) %>%
  summarise(
    mean_angle = mean(ppt_mean_angle),
    ci_angle = vector_confint(ppt_mean_angle)
  )
`summarise()` has grouped output by 'obj_shape_sign'. You can override using the `.groups` argument.
data_ppt <- dr_30_ppt_incl_clamped
data_exp <- dr_30_exp_incl_clamped

# set up plot
p <- data_exp %>%
  ggplot(
    aes(
      x = obj_shape_sign,
      y = mean_angle,
      color = obj_shape_sign,
      shape = targetAngle
    )
  ) +
  theme_classic() +
  theme(legend.position = "none") +
  labs(
    x = NULL,
    y = NULL
  )

# add horizontal lines
p <- p +
  geom_hline(
    yintercept = c(-30, 0, 30), linewidth = 0.4,
    colour = "#CCCCCC", linetype = "solid"
  ) +
  geom_hline(
    yintercept = c(-15, 15), linewidth = 0.4,
    colour = "#CCCCCC", linetype = "dashed"
  )

# add axis ticks
p <- p +
  scale_y_continuous(
    limits = c(-30, 30),
    breaks = c(-30, -15, 0, 15, 30),
    labels = c(-30, -15, 0, 15, 30)
  )

p <- p +
  scale_x_discrete(
    labels = c(
      "CW", "CCW"
    )
  )

# set font size to 11
p <- p +
  theme(text = element_text(size = 11))

# add data points
p <- p +
  geom_beeswarm(
    data = data_ppt,
    aes(
      x = obj_shape_sign,
      y = ppt_mean_angle,
      color = obj_shape_sign,
      shape = targetAngle
    ),
    size = 1,
    alpha = 0.2
  ) +
  geom_linerange(
    aes(
      ymin = mean_angle - ci_angle,
      ymax = mean_angle + ci_angle
    ),
    alpha = 0.5, lwd = 2
  ) +
  geom_point()

p <- p +
  scale_color_manual(
    values = c(palette$get("a-1"), palette$get("a-2"))
  )

p

# summary statistics
data_ppt %>%
  group_by(obj_shape_sign, targetAngle) %>%
  summarise(
    mean = mean(ppt_mean_angle),
    ci = vector_confint(ppt_mean_angle),
    n = n()
  )
`summarise()` has grouped output by 'obj_shape_sign'. You can override using the `.groups` argument.
# ANOVA using afex (identical values to ez but ez doesn't remove missing rows)
(temp_ANOVA <- aov_car(ppt_mean_angle ~ targetAngle * obj_shape_sign + Error(ppid / (targetAngle * obj_shape_sign)), data_ppt))
Anova Table (Type 3 tests)

Response: ppt_mean_angle
                      Effect          df    MSE        F   ges p.value
1                targetAngle 1.35, 39.16 113.20 10.24 **  .097    .001
2             obj_shape_sign       1, 29 170.89   6.81 *  .074    .014
3 targetAngle:obj_shape_sign 1.93, 55.97  11.77     0.38 <.001    .675
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘+’ 0.1 ‘ ’ 1

Sphericity correction method: GG 
bf <- anovaBF(ppt_mean_angle ~ targetAngle * obj_shape_sign + ppid,
  data = data.frame(data_ppt), whichRandom = "ppid", progress = FALSE
)
print(bf)
Bayes factor analysis
--------------
[1] obj_shape_sign + ppid                                            : 164.2226 ±0.77%
[2] targetAngle + ppid                                               : 457.2232 ±0.66%
[3] obj_shape_sign + targetAngle + ppid                              : 178501.1 ±1.06%
[4] obj_shape_sign + targetAngle + obj_shape_sign:targetAngle + ppid : 18848.22 ±1.39%

Against denominator:
  ppt_mean_angle ~ ppid 
---
Bayes factor type: BFlinearModel, JZS
bayesfactor_inclusion(bf)
Inclusion Bayes Factors (Model Averaged)

                           P(prior) P(posterior) Inclusion BF
ppid                           1.00         1.00             
obj_shape_sign                 0.60         1.00       287.36
targetAngle                    0.60         1.00       798.14
obj_shape_sign:targetAngle     0.20         0.10        0.421

* Compared among: all models
*    Priors odds: uniform-equal

4.3.2 Exclude strategy reaches

dr_30_ppt_excl_clamped <- dr_30_excl_clamp %>%
  group_by(ppid, obj_shape_sign, targetAngle) %>%
  summarise(
    ppt_mean_angle = mean(obj_angle_3cm_move),
    ppt_ci_angle = vector_confint(obj_angle_3cm_move)
  )
Warning: There were 3 warnings in `summarise()`.
The first warning was:
ℹ In argument: `ppt_ci_angle = vector_confint(obj_angle_3cm_move)`.
ℹ In group 37: `ppid = "dr_30_15"`, `obj_shape_sign = -1`, `targetAngle = 45`.
Caused by warning in `qt()`:
! NaNs produced
ℹ Run ]8;;ide:run:dplyr::last_dplyr_warnings()dplyr::last_dplyr_warnings()]8;; to see the 2 remaining warnings.`summarise()` has grouped output by 'ppid', 'obj_shape_sign'. You can override using the `.groups` argument.
dr_30_ppt_excl_clamped$ppid <- factor(dr_30_ppt_excl_clamped$ppid)
dr_30_ppt_excl_clamped$obj_shape_sign <- factor(dr_30_ppt_excl_clamped$obj_shape_sign)
dr_30_ppt_excl_clamped$targetAngle <- factor(dr_30_ppt_excl_clamped$targetAngle)

dr_30_exp_excl_clamped <- dr_30_ppt_excl_clamped %>%
  group_by(obj_shape_sign, targetAngle) %>%
  summarise(
    mean_angle = mean(ppt_mean_angle),
    ci_angle = vector_confint(ppt_mean_angle)
  )
`summarise()` has grouped output by 'obj_shape_sign'. You can override using the `.groups` argument.
data_ppt <- dr_30_ppt_excl_clamped
data_exp <- dr_30_exp_excl_clamped

# set up plot
p <- data_exp %>%
  ggplot(
    aes(
      x = obj_shape_sign,
      y = mean_angle,
      color = obj_shape_sign,
      shape = targetAngle
    )
  ) +
  theme_classic() +
  theme(legend.position = "none") +
  labs(
    x = NULL,
    y = NULL
  )

# add horizontal lines
p <- p +
  geom_hline(
    yintercept = c(-30, 0, 30), linewidth = 0.4,
    colour = "#CCCCCC", linetype = "solid"
  ) +
  geom_hline(
    yintercept = c(-15, 15), linewidth = 0.4,
    colour = "#CCCCCC", linetype = "dashed"
  )

# add axis ticks
p <- p +
  scale_y_continuous(
    limits = c(-30, 30),
    breaks = c(-30, -15, 0, 15, 30),
    labels = c(-30, -15, 0, 15, 30)
  )

p <- p +
  scale_x_discrete(
    labels = c(
      "CW", "CCW"
    )
  )

# set font size to 11
p <- p +
  theme(text = element_text(size = 11))

# add data points
p <- p +
  geom_beeswarm(
    data = data_ppt,
    aes(
      x = obj_shape_sign,
      y = ppt_mean_angle,
      color = obj_shape_sign,
      shape = targetAngle
    ),
    size = 1,
    alpha = 0.2
  ) +
  geom_linerange(
    aes(
      ymin = mean_angle - ci_angle,
      ymax = mean_angle + ci_angle
    ),
    alpha = 0.5, lwd = 2
  ) +
  geom_point()

p <- p +
  scale_color_manual(
    values = c(palette$get("a-1"), palette$get("a-2"))
  )

p

# summary statistics
data_ppt %>%
  group_by(obj_shape_sign, targetAngle) %>%
  summarise(
    mean = mean(ppt_mean_angle),
    ci = vector_confint(ppt_mean_angle),
    n = n()
  )
`summarise()` has grouped output by 'obj_shape_sign'. You can override using the `.groups` argument.
# ANOVA using afex (identical values to ez but ez doesn't remove missing rows)
(temp_ANOVA <- aov_car(ppt_mean_angle ~ targetAngle * obj_shape_sign + Error(ppid / (targetAngle * obj_shape_sign)), data_ppt))
Anova Table (Type 3 tests)

Response: ppt_mean_angle
                      Effect          df    MSE         F  ges p.value
1                targetAngle 1.56, 45.33 107.75 11.99 *** .119   <.001
2             obj_shape_sign       1, 29 110.13    3.92 + .028    .057
3 targetAngle:obj_shape_sign 1.83, 53.18  21.25    3.43 * .009    .044
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘+’ 0.1 ‘ ’ 1

Sphericity correction method: GG 
bf <- anovaBF(ppt_mean_angle ~ targetAngle * obj_shape_sign + ppid,
  data = data.frame(data_ppt), whichRandom = "ppid", progress = FALSE
)
print(bf)
Bayes factor analysis
--------------
[1] obj_shape_sign + ppid                                            : 2.234713 ±2.56%
[2] targetAngle + ppid                                               : 21151.1  ±0.61%
[3] obj_shape_sign + targetAngle + ppid                              : 81687.42 ±4.2%
[4] obj_shape_sign + targetAngle + obj_shape_sign:targetAngle + ppid : 18830.67 ±2.83%

Against denominator:
  ppt_mean_angle ~ ppid 
---
Bayes factor type: BFlinearModel, JZS
bayesfactor_inclusion(bf)
Inclusion Bayes Factors (Model Averaged)

                           P(prior) P(posterior) Inclusion BF
ppid                           1.00         1.00             
obj_shape_sign                 0.60         0.83         3.17
targetAngle                    0.60         1.00     2.51e+04
obj_shape_sign:targetAngle     0.20         0.15        0.732

* Compared among: all models
*    Priors odds: uniform-equal
# posthoc tests
(m1 <- emmeans(temp_ANOVA, ~ targetAngle * obj_shape_sign))
 targetAngle obj_shape_sign emmean   SE df lower.CL upper.CL
 X45         X.1             4.446 1.45 29    1.471    7.420
 X90         X.1            -2.462 1.52 29   -5.563    0.639
 X135        X.1            -0.603 1.82 29   -4.326    3.121
 X45         X1              2.849 1.61 29   -0.435    6.133
 X90         X1             -4.647 1.56 29   -7.835   -1.460
 X135        X1             -6.113 2.09 29  -10.393   -1.832

Confidence level used: 0.95 
pairs(m1)
 contrast           estimate   SE df t.ratio p.value
 X45 X.1 - X90 X.1      6.91 1.43 29   4.841  0.0005
 X45 X.1 - X135 X.1     5.05 2.12 29   2.383  0.1955
 X45 X.1 - X45 X1       1.60 1.56 29   1.027  0.9051
 X45 X.1 - X90 X1       9.09 1.88 29   4.834  0.0005
 X45 X.1 - X135 X1     10.56 2.66 29   3.976  0.0052
 X90 X.1 - X135 X.1    -1.86 1.83 29  -1.018  0.9081
 X90 X.1 - X45 X1      -5.31 2.03 29  -2.615  0.1256
 X90 X.1 - X90 X1       2.18 1.56 29   1.396  0.7287
 X90 X.1 - X135 X1      3.65 2.29 29   1.597  0.6070
 X135 X.1 - X45 X1     -3.45 2.71 29  -1.275  0.7956
 X135 X.1 - X90 X1      4.04 2.36 29   1.715  0.5333
 X135 X.1 - X135 X1     5.51 2.25 29   2.446  0.1739
 X45 X1 - X90 X1        7.50 1.67 29   4.492  0.0013
 X45 X1 - X135 X1       8.96 2.40 29   3.740  0.0095
 X90 X1 - X135 X1       1.47 1.53 29   0.956  0.9280

P value adjustment: tukey method for comparing a family of 6 estimates 

5 Hand Rotations

# helper function
average_circle <- function(num_vec) {
  # Convert vectors to radians
  vectors_rad <- lapply(num_vec, function(v) rad(v))

  # Calculate average for each dimension
  circular_mean <- mean(circular(vectors_rad), na.rm = TRUE)

  # Convert the average vector back to degrees
  deg(circular_mean)
}

# isolate all trials where baseline_block is TRUE
dr_30_baseline <- dr_30_all %>%
  filter(baseline_block == TRUE)

# make ppid, obj_shape, targetAngle factors
dr_30_baseline$ppid <- factor(dr_30_baseline$ppid)
dr_30_baseline$obj_shape <- factor(dr_30_baseline$obj_shape)
dr_30_baseline$targetAngle <- factor(dr_30_baseline$targetAngle)

rot_at_pickup_summary <- dr_30_baseline %>%
  group_by(ppid, obj_shape, targetAngle) %>%
  summarise(
    n()
  )
`summarise()` has grouped output by 'ppid', 'obj_shape'. You can override using the `.groups` argument.
# add empty columns
rot_at_pickup_summary$mean_rot_x_at_pickup <- NA
rot_at_pickup_summary$ci_rot_x_at_pickup <- NA
rot_at_pickup_summary$mean_rot_y_at_pickup <- NA
rot_at_pickup_summary$ci_rot_y_at_pickup <- NA
rot_at_pickup_summary$mean_rot_z_at_pickup <- NA
rot_at_pickup_summary$ci_rot_z_at_pickup <- NA

# loop through rows of rot_at_pickup_summary and calculate average rotation
for (i in 1:nrow(rot_at_pickup_summary)) {
  # get ppid, obj_shape, targetAngle
  row_ppid <- rot_at_pickup_summary$ppid[i]
  row_obj_shape <- rot_at_pickup_summary$obj_shape[i]
  row_targetAngle <- rot_at_pickup_summary$targetAngle[i]

  # get all rows for this ppid, obj_shape, targetAngle
  temp_data <- dr_30_baseline %>%
    filter(ppid == row_ppid, obj_shape == row_obj_shape, targetAngle == row_targetAngle)

  # get all hand_rot_x_at_pickup values
  rot_x <- temp_data$hand_rot_x_at_pickup

  # get all hand_rot_y_at_pickup values
  rot_y <- temp_data$hand_rot_y_at_pickup

  # get all hand_rot_z_at_pickup values
  rot_z <- temp_data$hand_rot_z_at_pickup

  # add to rot_at_pickup_summary
  rot_at_pickup_summary$mean_rot_x_at_pickup[i] <- average_circle(rot_x)
  rot_at_pickup_summary$ci_rot_x_at_pickup[i] <- vector_confint(rot_x)
  rot_at_pickup_summary$mean_rot_y_at_pickup[i] <- average_circle(rot_y)
  rot_at_pickup_summary$ci_rot_y_at_pickup[i] <- vector_confint(rot_y)
  rot_at_pickup_summary$mean_rot_z_at_pickup[i] <- average_circle(rot_z)
  rot_at_pickup_summary$ci_rot_z_at_pickup[i] <- vector_confint(rot_z)
}

# summarize
rot_at_pickup_summary2 <- rot_at_pickup_summary %>%
  group_by(obj_shape, targetAngle) %>%
  summarise(
    mean_rot_x_at_pickup2 = mean(mean_rot_x_at_pickup),
    ci_rot_x_at_pickup2 = vector_confint(mean_rot_x_at_pickup),
    mean_rot_y_at_pickup2 = mean(mean_rot_y_at_pickup),
    ci_rot_y_at_pickup2 = vector_confint(mean_rot_y_at_pickup),
    mean_rot_z_at_pickup2 = mean(mean_rot_z_at_pickup),
    ci_rot_z_at_pickup2 = vector_confint(mean_rot_z_at_pickup)
  )
`summarise()` has grouped output by 'obj_shape'. You can override using the `.groups` argument.
# set up plot
p <- rot_at_pickup_summary %>%
  ggplot(
    aes(
      x = obj_shape,
      y = mean_rot_x_at_pickup,
      color = targetAngle
    )
  ) +
  theme_classic() +
  theme(legend.position = "none") +
  labs(
    x = NULL,
    y = NULL
  ) +
  # add data points
  geom_beeswarm(
    aes(
      x = obj_shape,
      y = mean_rot_x_at_pickup,
      color = targetAngle
    ),
    size = 1,
    alpha = 0.2
  ) +
  geom_linerange(
    data = rot_at_pickup_summary2,
    aes(
      y = mean_rot_x_at_pickup2,
      ymin = mean_rot_x_at_pickup2 - ci_rot_x_at_pickup2,
      ymax = mean_rot_x_at_pickup2 + ci_rot_x_at_pickup2
    ),
    alpha = 0.5, lwd = 2
  ) +
  geom_point(
    data = rot_at_pickup_summary2,
    aes(
      x = obj_shape,
      y = mean_rot_x_at_pickup2,
      color = targetAngle
    )
  )

# same as above but add y in a different plot
q <- rot_at_pickup_summary %>%
  ggplot(
    aes(
      x = obj_shape,
      y = mean_rot_y_at_pickup,
      color = targetAngle
    )
  ) +
  theme_classic() +
  theme(legend.position = "none") +
  labs(
    x = NULL,
    y = NULL
  ) +
  # add data points
  geom_beeswarm(
    aes(
      x = obj_shape,
      y = mean_rot_y_at_pickup,
      color = targetAngle
    ),
    size = 1,
    alpha = 0.2
  ) +
  geom_linerange(
    data = rot_at_pickup_summary2,
    aes(
      y = mean_rot_y_at_pickup2,
      ymin = mean_rot_y_at_pickup2 - ci_rot_y_at_pickup2,
      ymax = mean_rot_y_at_pickup2 + ci_rot_y_at_pickup2
    ),
    alpha = 0.5, lwd = 2
  ) +
  geom_point(
    data = rot_at_pickup_summary2,
    aes(
      x = obj_shape,
      y = mean_rot_y_at_pickup2,
      color = targetAngle
    )
  )

# same as above but add z in a different plot
r <- rot_at_pickup_summary %>%
  ggplot(
    aes(
      x = obj_shape,
      y = mean_rot_z_at_pickup,
      color = targetAngle
    )
  ) +
  theme_classic() +
  theme(legend.position = "none") +
  labs(
    x = NULL,
    y = NULL
  ) +
  # add data points
  geom_beeswarm(
    aes(
      x = obj_shape,
      y = mean_rot_z_at_pickup,
      color = targetAngle
    ),
    size = 1,
    alpha = 0.2
  ) +
  geom_linerange(
    data = rot_at_pickup_summary2,
    aes(
      y = mean_rot_z_at_pickup2,
      ymin = mean_rot_z_at_pickup2 - ci_rot_z_at_pickup2,
      ymax = mean_rot_z_at_pickup2 + ci_rot_z_at_pickup2
    ),
    alpha = 0.5, lwd = 2
  ) +
  geom_point(
    data = rot_at_pickup_summary2,
    aes(
      x = obj_shape,
      y = mean_rot_z_at_pickup2,
      color = targetAngle
    )
  )

# plots
p

q

r

# ANOVA using afex (identical values to ez but ez doesn't remove missing rows)
(temp_ANOVA <- aov_car(mean_rot_x_at_pickup ~ obj_shape * targetAngle + Error(ppid / (obj_shape * targetAngle)), rot_at_pickup_summary))
Anova Table (Type 3 tests)

Response: mean_rot_x_at_pickup
                 Effect          df  MSE      F   ges p.value
1             obj_shape       1, 29 2.50   0.37 <.001    .547
2           targetAngle 1.76, 51.15 2.33 3.93 *  .001    .031
3 obj_shape:targetAngle 1.83, 53.02 1.37   1.42 <.001    .250
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘+’ 0.1 ‘ ’ 1

Sphericity correction method: GG 
bf <- anovaBF(mean_rot_x_at_pickup ~ obj_shape * targetAngle + ppid,
  data = data.frame(rot_at_pickup_summary), whichRandom = "ppid", progress = FALSE
)
print(bf)
Bayes factor analysis
--------------
[1] obj_shape + ppid                                       : 0.1978091 ±0.93%
[2] targetAngle + ppid                                     : 2.495498  ±0.81%
[3] obj_shape + targetAngle + ppid                         : 0.5158836 ±2.5%
[4] obj_shape + targetAngle + obj_shape:targetAngle + ppid : 0.1111915 ±2.06%

Against denominator:
  mean_rot_x_at_pickup ~ ppid 
---
Bayes factor type: BFlinearModel, JZS
bayesfactor_inclusion(bf)
Inclusion Bayes Factors (Model Averaged)

                      P(prior) P(posterior) Inclusion BF
ppid                      1.00         1.00             
obj_shape                 0.60         0.19        0.157
targetAngle               0.60         0.72         1.74
obj_shape:targetAngle     0.20         0.03        0.106

* Compared among: all models
*    Priors odds: uniform-equal
# posthoc tests
(m1 <- emmeans(temp_ANOVA, ~ obj_shape * targetAngle))
 obj_shape targetAngle emmean   SE df lower.CL upper.CL
 cube      X45          -4.73 1.49 29    -7.78   -1.682
 sphere    X45          -4.66 1.40 29    -7.52   -1.797
 cube      X90          -3.99 1.47 29    -6.99   -0.987
 sphere    X90          -3.95 1.46 29    -6.95   -0.962
 cube      X135         -3.95 1.45 29    -6.93   -0.975
 sphere    X135         -4.49 1.42 29    -7.39   -1.592

Confidence level used: 0.95 
pairs(m1)
 contrast                 estimate    SE df t.ratio p.value
 cube X45 - sphere X45    -0.07417 0.317 29  -0.234  0.9999
 cube X45 - cube X90      -0.74142 0.367 29  -2.018  0.3570
 cube X45 - sphere X90    -0.77803 0.468 29  -1.664  0.5651
 cube X45 - cube X135     -0.78146 0.307 29  -2.547  0.1437
 cube X45 - sphere X135   -0.23954 0.367 29  -0.654  0.9856
 sphere X45 - cube X90    -0.66724 0.328 29  -2.034  0.3484
 sphere X45 - sphere X90  -0.70386 0.298 29  -2.360  0.2036
 sphere X45 - cube X135   -0.70729 0.273 29  -2.590  0.1321
 sphere X45 - sphere X135 -0.16537 0.295 29  -0.560  0.9929
 cube X90 - sphere X90    -0.03662 0.344 29  -0.106  1.0000
 cube X90 - cube X135     -0.04004 0.306 29  -0.131  1.0000
 cube X90 - sphere X135    0.50187 0.435 29   1.153  0.8551
 sphere X90 - cube X135   -0.00342 0.323 29  -0.011  1.0000
 sphere X90 - sphere X135  0.53849 0.405 29   1.329  0.7670
 cube X135 - sphere X135   0.54192 0.340 29   1.594  0.6087

P value adjustment: tukey method for comparing a family of 6 estimates 
# Fin
LS0tDQp0aXRsZTogIlN1cHBsZW1lbnRhcnkgRGF0YSBBbmFseXNpcyINCmF1dGhvcjogIlNoYW5hYSBNb2RjaGFsaW5nYW0iDQpkYXRlOiAnMjAyMycNCm91dHB1dDogDQogIGh0bWxfbm90ZWJvb2s6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQogICAgZGZfcHJpbnQ6IHBhZ2VkDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQotLS0NCg0KYGBge3IgaW5jbHVkZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCnJtKGxpc3QgPSBscygpKSAjIGNsZWFuIGVudmlyb25tZW50DQoNCnNvdXJjZSgiLi4vc3JjL2hlbHBlcl9mdW5jcy5SIikNCmxpYnJhcnkoZGF0YS50YWJsZSkNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShmdXR1cmUpICMgZm9yIHBhcmFsbGVsIHByb2Nlc3NpbmcNCmxpYnJhcnkoY29sbGVjdGlvbnMpDQpsaWJyYXJ5KGdnYmVlc3dhcm0pDQoNCmxpYnJhcnkoZXopICMgZm9yIEFOT1ZBcyBOT1RFOmV6IFRIRSBhZmV4IFBBQ0tBR0UgSVMgQSBMT1QgQkVUVEVSIEZPUiBQT1NUSE9DIFRFU1RTDQpsaWJyYXJ5KGFmZXgpICMgZm9yIEFOT1ZBcw0KbGlicmFyeShlbW1lYW5zKQ0KbGlicmFyeShlZmZlY3RzaXplKSAjIGZvciBldGEtc3F1YXJlZA0KbGlicmFyeShCYXllc0ZhY3RvcikNCmxpYnJhcnkoYmF5ZXN0ZXN0UikNCg0KbGlicmFyeShSZWFjaCkgIyBmcm9tIGdpdGh1YjogdGhhcnRibS9SZWFjaA0KbGlicmFyeShkYWJlc3RyKQ0KDQpsaWJyYXJ5KGNpcmN1bGFyKSAjIGZvciByb3RhdGlvbnMNCmxpYnJhcnkocGxvdGx5KQ0KDQojIEhlbHBlciBmdW5jdGlvbnMNCiMjIyMjIEhlbHBlciBmdW5jdGlvbnMgIyMjIyMNCnNsb3BlIDwtIGZ1bmN0aW9uKHgsIHkpIHsNCiAgcmV0dXJuKGNvdih4LCB5KSAvIHZhcih4KSkNCn0NCg0KaW50ZXJjZXB0IDwtIGZ1bmN0aW9uKHgsIHksIHNsb3BlKSB7DQogIGIgPC0gbWVhbih5KSAtIChzbG9wZSAqIG1lYW4oeCkpDQogIHJldHVybihiKQ0KfQ0KDQojIHNldHRpbmdzDQpzYXZlX3Bsb3RzIDwtIEZBTFNFDQpgYGANCg0KIyBEYXRhIEltcG9ydCBhbmQgQ2xlYW5pbmcNCmBgYHtyfQ0KIyBpbXBvcnQgZGF0YQ0KZGF0YV9wYXRoIDwtICIuLi9kYXRhL3ByZXByb2Nlc3NlZC9vbW5pYnVzL29tbmlidXNfYmxfY29ycmVjdGVkX3BpY2t1cHMuY3N2Ig0KDQphbGxfZGF0YSA8LSBmcmVhZChkYXRhX3BhdGgpDQoNCiMjIFNldHVwICMjDQpwYWxldHRlIDwtIGRpY3QoDQogIGxpc3QoDQogICAgInMzMCIgPSAiI2EzMGYxNSIsDQogICAgImQzMCIgPSAiIzA3NTA5YiIsDQogICAgInMzMC1hIiA9ICIjZmI2OTQ5IiwNCiAgICAiZDMwLWEiID0gIiM2YWFmZDIiLA0KICAgICJhLTEiID0gIiM0ZjFiMzEiLA0KICAgICJhLTIiID0gIiNkNjgxOWIiDQogICkNCikNCg0KIyMgSXNvbGF0ZSBleHBlcmltZW50cyBhbmQgc3VtbWFyaXplICMjDQpzcl8zMF9hbGwgPC0gYWxsX2RhdGEgJT4lDQogIGZpbHRlcihleHAgPT0gInNyXzMwIikgJT4lDQogIG11dGF0ZSh1bnNpZ25lZF9vYmpfYW5nbGUgPSBvYmpfYW5nbGVfM2NtX21vdmUgKiBvYmpfc2hhcGVfc2lnbiAqIC0xKSAlPiUNCiAgbXV0YXRlKHVuc2lnbmVkX2hhbmRfYW5nbGUgPSBoYW5kX2FuZ2xlXzNjbV9tb3ZlICogb2JqX3NoYXBlX3NpZ24gKiAtMSkNCg0Kc3JfMzBfcHB0X3RyYWluaW5nIDwtIHNyXzMwX2FsbCAlPiUNCiAgZmlsdGVyKGJsb2NrX251bSA9PSAxNikgJT4lDQogIG11dGF0ZSh0cmlhbF9zZXQgPSBjYXNlX3doZW4oDQogICAgdHJpYWxfbnVtIDw9IDE0MSB+IDEsDQogICAgdHJpYWxfbnVtID49IDMxMCB+IDIsDQogICAgVFJVRSB+IDEwMA0KICApKQ0KDQpzcl8zMF9jbGFtcGVkIDwtIHNyXzMwX2FsbCAlPiUNCiAgZmlsdGVyKGJsb2NrX251bSA+IDE2LCB0eXBlID09ICJjbGFtcGVkIikgJT4lDQogIG11dGF0ZSh0cmFpbmVkX29ial9mYWN0b3IgPSBjYXNlX3doZW4oDQogICAgdHJhaW5lZGZpcnN0X29ial9zaGFwZSA9PSBvYmpfc2hhcGUgfiAidHJhaW5lZF9vYmoiLA0KICAgIFRSVUUgfiAidW50cmFpbmVkX29iaiINCiAgKSkgJT4lDQogIG11dGF0ZSh0cmFpbmVkX2hhbmRfZmFjdG9yID0gY2FzZV93aGVuKA0KICAgIGhhbmQgPT0gInIiIH4gInRyYWluZWRfaGFuZCIsDQogICAgVFJVRSB+ICJ1bnRyYWluZWRfaGFuZCINCiAgKSkgJT4lDQogIG11dGF0ZSh0cmFpbmVkX29ial9oYW5kX2ZhY3RvciA9IHBhc3RlMCh0cmFpbmVkX29ial9mYWN0b3IsICJfIiwgdHJhaW5lZF9oYW5kX2ZhY3RvcikpDQoNCiMjIyBEUiAzMCAjIyMNCmRyXzMwX2FsbCA8LSBhbGxfZGF0YSAlPiUNCiAgZmlsdGVyKGV4cCA9PSAiZHJfMzAiKSAlPiUNCiAgbXV0YXRlKHVuc2lnbmVkX29ial9hbmdsZSA9IG9ial9hbmdsZV8zY21fbW92ZSAqIG9ial9zaGFwZV9zaWduICogLTEpICU+JQ0KICBtdXRhdGUodW5zaWduZWRfaGFuZF9hbmdsZSA9IGhhbmRfYW5nbGVfM2NtX21vdmUgKiBvYmpfc2hhcGVfc2lnbiAqIC0xKQ0KDQpkcl8zMF9wcHRfdHJhaW5pbmcgPC0gZHJfMzBfYWxsICU+JQ0KICBmaWx0ZXIoYmxvY2tfbnVtID09IDcpICU+JQ0KICBtdXRhdGUodHJpYWxfc2V0ID0gY2FzZV93aGVuKA0KICAgIHRyaWFsX251bSA8PSA3OCB+IDEsDQogICAgdHJpYWxfbnVtID49IDI0NyB+IDIsDQogICAgVFJVRSB+IDEwMA0KICApKQ0KDQojIG5vdGU6IGJsb2NrcyA4IGFuZCAxMSBhcmUgaW5jbHVkZSBjbGFtcHMsIDEzIGlzIGV4Y2x1ZGUgY2xhbXBzDQpkcl8zMF9pbmNsX2NsYW1wIDwtIGRyXzMwX2FsbCAlPiUNCiAgZmlsdGVyKGJsb2NrX251bSAlaW4lIGMoOCwgMTEpKQ0KDQpkcl8zMF9leGNsX2NsYW1wIDwtIGRyXzMwX2FsbCAlPiUNCiAgZmlsdGVyKGJsb2NrX251bSAlaW4lIGMoMTMsIDE0KSkNCg0KIyBib3RoIGV4cGVyaW1lbnQgcmJpbmQNCmJvdGhfcHB0X3RyYWluaW5nIDwtIHJiaW5kKHNyXzMwX3BwdF90cmFpbmluZywgZHJfMzBfcHB0X3RyYWluaW5nKQ0KYGBgIA0KDQojIER1YWwgTGVhcm5pbmcgRGlmZnMNCg0KIyMgSW5jbHVkaW5nIFN0cmF0ZWd5DQpgYGB7cn0NCmRyXzMwX3BwdF9pbmNsX2NsYW1wZWQgPC0gZHJfMzBfaW5jbF9jbGFtcCAlPiUNCiAgZ3JvdXBfYnkocHBpZCwgb2JqX3NoYXBlX3NpZ24pICU+JQ0KICBzdW1tYXJpc2UoDQogICAgcHB0X21lYW5fYW5nbGUgPSBtZWFuKG9ial9hbmdsZV8zY21fbW92ZSksDQogICAgcHB0X2NpX2FuZ2xlID0gdmVjdG9yX2NvbmZpbnQob2JqX2FuZ2xlXzNjbV9tb3ZlKQ0KICApDQoNCmRyXzMwX3BwdF9pbmNsX2NsYW1wZWQkb2JqX3NoYXBlX3NpZ24gPC0gZmFjdG9yKA0KICBkcl8zMF9wcHRfaW5jbF9jbGFtcGVkJG9ial9zaGFwZV9zaWduDQopDQoNCmRyXzMwX2V4cF9pbmNsX2NsYW1wZWQgPC0gZHJfMzBfcHB0X2luY2xfY2xhbXBlZCAlPiUNCiAgZ3JvdXBfYnkob2JqX3NoYXBlX3NpZ24pICU+JQ0KICBzdW1tYXJpc2UoDQogICAgbWVhbl9hbmdsZSA9IG1lYW4ocHB0X21lYW5fYW5nbGUpLA0KICAgIGNpX2FuZ2xlID0gdmVjdG9yX2NvbmZpbnQocHB0X21lYW5fYW5nbGUpDQogICkNCg0KIyBhZGQgYSBkaWZmZXJlbmNlIGNvbHVtbg0KZHJfMzBfcHB0X2luY2xfY2xhbXBlZCA8LSBkcl8zMF9wcHRfaW5jbF9jbGFtcGVkICU+JQ0KICBncm91cF9ieShwcGlkKSAlPiUNCiAgbXV0YXRlKA0KICAgIGRpZmYgPSBwcHRfbWVhbl9hbmdsZSAtIGxhZyhwcHRfbWVhbl9hbmdsZSkNCiAgKQ0KDQojIHBsb3QgdGhlIHRyaWFsIHNldHMNCnAgPC0gZHJfMzBfcHB0X2luY2xfY2xhbXBlZCAlPiUNCiAgZ2dwbG90KA0KICAgIGFlcygNCiAgICAgIHggPSBvYmpfc2hhcGVfc2lnbiwgeSA9IHBwdF9tZWFuX2FuZ2xlLA0KICAgICAgY29sb3VyID0gcHBpZA0KICAgICkNCiAgKSArDQogIHRoZW1lX2NsYXNzaWMoKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKw0KICBsYWJzKA0KICAgIHggPSAiVHJpYWwgU2V0IiwNCiAgICB5ID0gIkhhbmQgQW5nbGUgKMKwKSINCiAgKSArDQogIGdlb21fcG9pbnQoKSArDQogIGdlb21fbGluZShhZXMoZ3JvdXAgPSBwcGlkKSwgYWxwaGEgPSAwLjIpDQoNCmdncGxvdGx5KHApDQoNCiMgcGxvdCB0aGUgZGlmZnMNCnAgPC0gZHJfMzBfcHB0X2luY2xfY2xhbXBlZCAlPiUNCiAgZmlsdGVyKG9ial9zaGFwZV9zaWduID09IDEpICU+JQ0KICBnZ3Bsb3QoDQogICAgYWVzKA0KICAgICAgeCA9IG9ial9zaGFwZV9zaWduLA0KICAgICAgY29sb3VyID0gcHBpZA0KICAgICkNCiAgKSArDQogIHRoZW1lX2NsYXNzaWMoKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKw0KICBnZW9tX2hsaW5lKA0KICAgIHlpbnRlcmNlcHQgPSBjKDApLCBsaW5ld2lkdGggPSAwLjQsDQogICAgY29sb3VyID0gIiNDQ0NDQ0MiLCBsaW5ldHlwZSA9ICJkYXNoZWQiDQogICkgKw0KICAjIGFkZCBkYXRhDQogIGdlb21fYmVlc3dhcm0oDQogICAgYWVzKA0KICAgICAgeSA9IGRpZmYNCiAgICApLA0KICAgIGFscGhhID0gMC41LA0KICAgIHNpemUgPSAxDQogICkNCg0KZ2dwbG90bHkocCkNCmBgYA0KDQpSZW1vdmluZyBwcHQgImRyXzMwXzIiDQpgYGB7cn0NCmRhdGFfcHB0IDwtIGRyXzMwX3BwdF9pbmNsX2NsYW1wZWQgJT4lDQogIGZpbHRlcihwcGlkICE9ICJkcl8zMF8yIikNCg0KIyBzdW1tYXJ5IHN0YXRpc3RpY3MNCmRhdGFfcHB0ICU+JSANCiAgZ3JvdXBfYnkob2JqX3NoYXBlX3NpZ24pICU+JSANCiAgc3VtbWFyaXNlKA0KICAgIG1lYW4gPSBtZWFuKHBwdF9tZWFuX2FuZ2xlKSwNCiAgICBjaSA9IHZlY3Rvcl9jb25maW50KHBwdF9tZWFuX2FuZ2xlKSwNCiAgICBuID0gbigpDQogICkNCmBgYA0KYGBge3J9DQojIENvbXBhcmlzb24gc3RhdHMNCiMgcGFpcmVkIHQtdGVzdA0KZ3JvdXAxIDwtIGRhdGFfcHB0ICU+JSANCiAgZmlsdGVyKG9ial9zaGFwZV9zaWduID09ICItMSIpICU+JSANCiAgcHVsbChwcHRfbWVhbl9hbmdsZSkNCg0KZ3JvdXAyIDwtIGRhdGFfcHB0ICU+JQ0KICBmaWx0ZXIob2JqX3NoYXBlX3NpZ24gPT0gIjEiKSAlPiUgDQogIHB1bGwocHB0X21lYW5fYW5nbGUpDQoNCmRpZmZzIDwtIGdyb3VwMiAtIGdyb3VwMQ0KdC50ZXN0KGRpZmZzKQ0KDQojIEVmZmVjdCBzaXplDQpjb2hlbi5kKGdyb3VwMSwgZ3JvdXAyKQ0KDQojIEJheWVzIGZhY3Rvcg0KdHRlc3RCRih4ID0gZGlmZnMpDQpgYGANCg0KIyMgRXhjbHVkaW5nIHN0cmF0ZWd5DQpgYGB7cn0NCmRyXzMwX3BwdF9leGNsX2NsYW1wZWQgPC0gZHJfMzBfZXhjbF9jbGFtcCAlPiUNCiAgZ3JvdXBfYnkocHBpZCwgb2JqX3NoYXBlX3NpZ24pICU+JQ0KICBzdW1tYXJpc2UoDQogICAgcHB0X21lYW5fYW5nbGUgPSBtZWFuKG9ial9hbmdsZV8zY21fbW92ZSksDQogICAgcHB0X2NpX2FuZ2xlID0gdmVjdG9yX2NvbmZpbnQob2JqX2FuZ2xlXzNjbV9tb3ZlKQ0KICApDQoNCmRyXzMwX3BwdF9leGNsX2NsYW1wZWQkb2JqX3NoYXBlX3NpZ24gPC0gZmFjdG9yKA0KICBkcl8zMF9wcHRfZXhjbF9jbGFtcGVkJG9ial9zaGFwZV9zaWduDQopDQoNCmRyXzMwX2V4cF9leGNsX2NsYW1wZWQgPC0gZHJfMzBfcHB0X2V4Y2xfY2xhbXBlZCAlPiUNCiAgZ3JvdXBfYnkob2JqX3NoYXBlX3NpZ24pICU+JQ0KICBzdW1tYXJpc2UoDQogICAgbWVhbl9hbmdsZSA9IG1lYW4ocHB0X21lYW5fYW5nbGUpLA0KICAgIGNpX2FuZ2xlID0gdmVjdG9yX2NvbmZpbnQocHB0X21lYW5fYW5nbGUpDQogICkNCg0KIyBhZGQgYSBkaWZmZXJlbmNlIGNvbHVtbg0KZHJfMzBfcHB0X2V4Y2xfY2xhbXBlZCA8LSBkcl8zMF9wcHRfZXhjbF9jbGFtcGVkICU+JQ0KICBncm91cF9ieShwcGlkKSAlPiUNCiAgbXV0YXRlKA0KICAgIGRpZmYgPSBwcHRfbWVhbl9hbmdsZSAtIGxhZyhwcHRfbWVhbl9hbmdsZSkNCiAgKQ0KDQojIHBsb3QgdGhlIHRyaWFsIHNldHMNCnAgPC0gZHJfMzBfcHB0X2V4Y2xfY2xhbXBlZCAlPiUNCiAgZ2dwbG90KA0KICAgIGFlcygNCiAgICAgIHggPSBvYmpfc2hhcGVfc2lnbiwgeSA9IHBwdF9tZWFuX2FuZ2xlLA0KICAgICAgY29sb3VyID0gcHBpZA0KICAgICkNCiAgKSArDQogIHRoZW1lX2NsYXNzaWMoKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKw0KICBsYWJzKA0KICAgIHggPSAiVHJpYWwgU2V0IiwNCiAgICB5ID0gIkhhbmQgQW5nbGUgKMKwKSINCiAgKSArDQogIGdlb21fcG9pbnQoKSArDQogIGdlb21fbGluZShhZXMoZ3JvdXAgPSBwcGlkKSwgYWxwaGEgPSAwLjIpDQoNCmdncGxvdGx5KHApDQoNCiMgcGxvdCB0aGUgZGlmZnMNCnAgPC0gZHJfMzBfcHB0X2V4Y2xfY2xhbXBlZCAlPiUNCiAgZmlsdGVyKG9ial9zaGFwZV9zaWduID09IDEpICU+JQ0KICBnZ3Bsb3QoDQogICAgYWVzKA0KICAgICAgeCA9IG9ial9zaGFwZV9zaWduLA0KICAgICAgY29sb3VyID0gcHBpZA0KICAgICkNCiAgKSArDQogIHRoZW1lX2NsYXNzaWMoKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKw0KICBnZW9tX2hsaW5lKA0KICAgIHlpbnRlcmNlcHQgPSBjKDApLCBsaW5ld2lkdGggPSAwLjQsDQogICAgY29sb3VyID0gIiNDQ0NDQ0MiLCBsaW5ldHlwZSA9ICJkYXNoZWQiDQogICkgKw0KICAjIGFkZCBkYXRhDQogIGdlb21fYmVlc3dhcm0oDQogICAgYWVzKA0KICAgICAgeSA9IGRpZmYNCiAgICApLA0KICAgIGFscGhhID0gMC41LA0KICAgIHNpemUgPSAxDQogICkNCg0KZ2dwbG90bHkocCkNCmBgYA0KDQpSZW1vdmluZyBwcHQgImRyXzMwXzIiDQpgYGB7cn0NCmRhdGFfcHB0IDwtIGRyXzMwX3BwdF9leGNsX2NsYW1wZWQgJT4lDQogIGZpbHRlcihwcGlkICE9ICJkcl8zMF8yIikNCg0KIyBzdW1tYXJ5IHN0YXRpc3RpY3MNCmRhdGFfcHB0ICU+JSANCiAgZ3JvdXBfYnkob2JqX3NoYXBlX3NpZ24pICU+JSANCiAgc3VtbWFyaXNlKA0KICAgIG1lYW4gPSBtZWFuKHBwdF9tZWFuX2FuZ2xlKSwNCiAgICBjaSA9IHZlY3Rvcl9jb25maW50KHBwdF9tZWFuX2FuZ2xlKSwNCiAgICBuID0gbigpDQogICkNCmBgYA0KYGBge3J9DQojIENvbXBhcmlzb24gc3RhdHMNCiMgcGFpcmVkIHQtdGVzdA0KZ3JvdXAxIDwtIGRhdGFfcHB0ICU+JSANCiAgZmlsdGVyKG9ial9zaGFwZV9zaWduID09ICItMSIpICU+JSANCiAgcHVsbChwcHRfbWVhbl9hbmdsZSkNCg0KZ3JvdXAyIDwtIGRhdGFfcHB0ICU+JQ0KICBmaWx0ZXIob2JqX3NoYXBlX3NpZ24gPT0gIjEiKSAlPiUgDQogIHB1bGwocHB0X21lYW5fYW5nbGUpDQoNCmRpZmZzIDwtIGdyb3VwMiAtIGdyb3VwMQ0KdC50ZXN0KGRpZmZzKQ0KDQojIEVmZmVjdCBzaXplDQpjb2hlbi5kKGdyb3VwMSwgZ3JvdXAyKQ0KDQojIEJheWVzIGZhY3Rvcg0KdHRlc3RCRih4ID0gZGlmZnMpDQpgYGANCg0KIyBTaW5nbGUgTGVhcm5pbmcNCiMjIFRyYWluaW5nIFBoYXNlIFRyaWFsIFNldHMgLSBSZWFjaCBTdGVwDQpgYGB7cn0NCnNyXzMwX3BwdF90cmlhbF9zZXRzIDwtIHNyXzMwX3BwdF90cmFpbmluZyAlPiUNCiAgZmlsdGVyKHRyaWFsX3NldCA8IDUpICU+JQ0KICBncm91cF9ieShwcGlkLCB0cmlhbF9zZXQsIHRhcmdldEFuZ2xlKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIG1lYW5fdHJpYWxfc2V0X2FuZ2xlID0gbWVhbih1bnNpZ25lZF9oYW5kX2FuZ2xlKSwNCiAgICBuKCkNCiAgKQ0KDQpzcl8zMF9wcHRfdHJpYWxfc2V0cyRwcGlkIDwtIGFzLmZhY3Rvcihzcl8zMF9wcHRfdHJpYWxfc2V0cyRwcGlkKQ0Kc3JfMzBfcHB0X3RyaWFsX3NldHMkdHJpYWxfc2V0IDwtIGFzLmZhY3Rvcihzcl8zMF9wcHRfdHJpYWxfc2V0cyR0cmlhbF9zZXQpDQpzcl8zMF9wcHRfdHJpYWxfc2V0cyR0YXJnZXRBbmdsZSA8LSBhcy5mYWN0b3Ioc3JfMzBfcHB0X3RyaWFsX3NldHMkdGFyZ2V0QW5nbGUpDQoNCnNyXzMwX3RyaWFsX3NldF9kZXZzIDwtIHNyXzMwX3BwdF90cmlhbF9zZXRzICU+JQ0KICBncm91cF9ieSh0cmlhbF9zZXQsIHRhcmdldEFuZ2xlKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIHRyaWFsX3NldF9tZWFuID0gbWVhbihtZWFuX3RyaWFsX3NldF9hbmdsZSksDQogICAgdHJpYWxfc2V0X2NpID0gdmVjdG9yX2NvbmZpbnQobWVhbl90cmlhbF9zZXRfYW5nbGUpDQogICkNCg0KZGF0YV9wcHQgPC0gc3JfMzBfcHB0X3RyaWFsX3NldHMNCmRhdGFfdHJpYWxfc2V0IDwtIHNyXzMwX3RyaWFsX3NldF9kZXZzDQoNCiMgc2V0IHVwIHBsb3QNCnAgPC0gZGF0YV90cmlhbF9zZXQgJT4lDQogIGdncGxvdCgNCiAgICBhZXMoDQogICAgICB4ID0gdHJpYWxfc2V0LCB5ID0gdHJpYWxfc2V0X21lYW4NCiAgICApDQogICkgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsNCiAgbGFicygNCiAgICB4ID0gTlVMTCwNCiAgICB5ID0gIkhhbmQgQW5nbGUgKMKwKSINCiAgKQ0KDQojIGFkZCBob3Jpem9udGFsIGxpbmVzDQpwIDwtIHAgKw0KICBnZW9tX2hsaW5lKA0KICAgIHlpbnRlcmNlcHQgPSBjKDAsIDMwKSwgbGluZXdpZHRoID0gMC40LA0KICAgIGNvbG91ciA9ICIjQ0NDQ0NDIiwgbGluZXR5cGUgPSAic29saWQiDQogICkgKw0KICBnZW9tX2hsaW5lKA0KICAgIHlpbnRlcmNlcHQgPSBjKDE1KSwgbGluZXdpZHRoID0gMC40LA0KICAgIGNvbG91ciA9ICIjQ0NDQ0NDIiwgbGluZXR5cGUgPSAiZGFzaGVkIg0KICApDQoNCiMgYWRkIGF4aXMgdGlja3MNCnAgPC0gcCArDQogIHNjYWxlX3lfY29udGludW91cygNCiAgICBsaW1pdHMgPSBjKC0xNSwgNDApLA0KICAgIGJyZWFrcyA9IGMoMCwgMTUsIDMwKSwNCiAgICBsYWJlbHMgPSBjKDAsIDE1LCAzMCkNCiAgKQ0KDQojIHNldCBmb250IHNpemUgdG8gMTENCnAgPC0gcCArDQogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSkNCg0KIyBhZGQgZGF0YSBwb2ludHMNCnAgPC0gcCArDQogIGdlb21fYmVlc3dhcm0oDQogICAgZGF0YSA9IGRhdGFfcHB0LA0KICAgIGFlcyh5ID0gbWVhbl90cmlhbF9zZXRfYW5nbGUsIGNvbG91ciA9IHRhcmdldEFuZ2xlKSwNCiAgICBhbHBoYSA9IDAuNSwNCiAgICBzaXplID0gMQ0KICApICsNCiAgZ2VvbV9saW5lcmFuZ2UoYWVzKA0KICAgIHltaW4gPSB0cmlhbF9zZXRfbWVhbiAtIHRyaWFsX3NldF9jaSwNCiAgICB5bWF4ID0gdHJpYWxfc2V0X21lYW4gKyB0cmlhbF9zZXRfY2kNCiAgKSwgYWxwaGEgPSAwLjEsIGx3ZCA9IDIpICsNCiAgZ2VvbV9wb2ludCgpDQoNCiMgcCA8LSBwICsNCiMgICBzY2FsZV9jb2xvcl9tYW51YWwoDQojICAgICB2YWx1ZXMgPSBjKA0KIyAgICAgICAiIzU1NTU1NSIsICIjNTU1NTU1Ig0KIyAgICAgKQ0KIyAgICkNCg0KcCA8LSBwICsNCiAgc2NhbGVfeF9kaXNjcmV0ZSgNCiAgICBsYWJlbHMgPSBjKA0KICAgICAgIkluaXRcblQiLCAiRmluXG5UIg0KICAgICkNCiAgKQ0KDQpwDQpgYGANCg0KDQpgYGB7cn0NCiMgQU5PVkEgdXNpbmcgYWZleCAoaWRlbnRpY2FsIHZhbHVlcyB0byBleiBidXQgZXogZG9lc24ndCByZW1vdmUgbWlzc2luZyByb3dzKQ0KKHRlbXBfQU5PVkEgPC0gYW92X2NhcihtZWFuX3RyaWFsX3NldF9hbmdsZSB+IHRhcmdldEFuZ2xlICogdHJpYWxfc2V0ICsgRXJyb3IocHBpZCAvICh0YXJnZXRBbmdsZSAqIHRyaWFsX3NldCkpLCBkYXRhX3BwdCkpDQoNCmJmIDwtIGFub3ZhQkYobWVhbl90cmlhbF9zZXRfYW5nbGUgfiB0YXJnZXRBbmdsZSAqIHRyaWFsX3NldCArIHBwaWQsDQogIGRhdGEgPSBkYXRhLmZyYW1lKGRhdGFfcHB0KSwgd2hpY2hSYW5kb20gPSAicHBpZCIsIHByb2dyZXNzID0gRkFMU0UNCikNCnByaW50KGJmKQ0KYmF5ZXNmYWN0b3JfaW5jbHVzaW9uKGJmKQ0KYGBgDQoNCiMjIFRyYWluaW5nIFBoYXNlIFRyaWFsIFNldHMgLSBUcmFuc3BvcnQgU3RlcA0KYGBge3J9DQpzcl8zMF9wcHRfdHJpYWxfc2V0cyA8LSBzcl8zMF9wcHRfdHJhaW5pbmcgJT4lDQogIGZpbHRlcih0cmlhbF9zZXQgPCA1KSAlPiUNCiAgZ3JvdXBfYnkocHBpZCwgdHJpYWxfc2V0LCB0YXJnZXRBbmdsZSkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBtZWFuX3RyaWFsX3NldF9hbmdsZSA9IG1lYW4odW5zaWduZWRfb2JqX2FuZ2xlKQ0KICApDQoNCnNyXzMwX3BwdF90cmlhbF9zZXRzJHBwaWQgPC0gYXMuZmFjdG9yKHNyXzMwX3BwdF90cmlhbF9zZXRzJHBwaWQpDQpzcl8zMF9wcHRfdHJpYWxfc2V0cyR0cmlhbF9zZXQgPC0gYXMuZmFjdG9yKHNyXzMwX3BwdF90cmlhbF9zZXRzJHRyaWFsX3NldCkNCnNyXzMwX3BwdF90cmlhbF9zZXRzJHRhcmdldEFuZ2xlIDwtIGFzLmZhY3Rvcihzcl8zMF9wcHRfdHJpYWxfc2V0cyR0YXJnZXRBbmdsZSkNCg0Kc3JfMzBfdHJpYWxfc2V0X2RldnMgPC0gc3JfMzBfcHB0X3RyaWFsX3NldHMgJT4lDQogIGdyb3VwX2J5KHRyaWFsX3NldCwgdGFyZ2V0QW5nbGUpICU+JQ0KICBzdW1tYXJpc2UoDQogICAgdHJpYWxfc2V0X21lYW4gPSBtZWFuKG1lYW5fdHJpYWxfc2V0X2FuZ2xlKSwNCiAgICB0cmlhbF9zZXRfY2kgPSB2ZWN0b3JfY29uZmludChtZWFuX3RyaWFsX3NldF9hbmdsZSkNCiAgKQ0KDQpkYXRhX3BwdCA8LSBzcl8zMF9wcHRfdHJpYWxfc2V0cw0KZGF0YV90cmlhbF9zZXQgPC0gc3JfMzBfdHJpYWxfc2V0X2RldnMNCg0KIyBzZXQgdXAgcGxvdA0KcCA8LSBkYXRhX3RyaWFsX3NldCAlPiUNCiAgZ2dwbG90KA0KICAgIGFlcygNCiAgICAgIHggPSB0cmlhbF9zZXQsIHkgPSB0cmlhbF9zZXRfbWVhbg0KICAgICkNCiAgKSArDQogIHRoZW1lX2NsYXNzaWMoKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKw0KICBsYWJzKA0KICAgIHggPSBOVUxMLA0KICAgIHkgPSBOVUxMDQogICkNCg0KIyBhZGQgaG9yaXpvbnRhbCBsaW5lcw0KcCA8LSBwICsNCiAgZ2VvbV9obGluZSgNCiAgICB5aW50ZXJjZXB0ID0gYygwLCAzMCksIGxpbmV3aWR0aCA9IDAuNCwNCiAgICBjb2xvdXIgPSAiI0NDQ0NDQyIsIGxpbmV0eXBlID0gInNvbGlkIg0KICApICsNCiAgZ2VvbV9obGluZSgNCiAgICB5aW50ZXJjZXB0ID0gYygxNSksIGxpbmV3aWR0aCA9IDAuNCwNCiAgICBjb2xvdXIgPSAiI0NDQ0NDQyIsIGxpbmV0eXBlID0gImRhc2hlZCINCiAgKQ0KDQojIGFkZCBheGlzIHRpY2tzDQpwIDwtIHAgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoDQogICAgbGltaXRzID0gYygtMTUsIDQwKSwNCiAgICBicmVha3MgPSBjKDAsIDE1LCAzMCksDQogICAgbGFiZWxzID0gYygwLCAxNSwgMzApDQogICkNCg0KIyBzZXQgZm9udCBzaXplIHRvIDExDQpwIDwtIHAgKw0KICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSkpDQoNCiMgYWRkIGRhdGEgcG9pbnRzDQpwIDwtIHAgKw0KICBnZW9tX2JlZXN3YXJtKA0KICAgIGRhdGEgPSBkYXRhX3BwdCwNCiAgICBhZXMoeSA9IG1lYW5fdHJpYWxfc2V0X2FuZ2xlLCBjb2xvdXIgPSB0YXJnZXRBbmdsZSksDQogICAgYWxwaGEgPSAwLjUsDQogICAgc2l6ZSA9IDENCiAgKSArDQogIGdlb21fbGluZXJhbmdlKGFlcygNCiAgICB5bWluID0gdHJpYWxfc2V0X21lYW4gLSB0cmlhbF9zZXRfY2ksDQogICAgeW1heCA9IHRyaWFsX3NldF9tZWFuICsgdHJpYWxfc2V0X2NpDQogICksIGFscGhhID0gMC4xLCBsd2QgPSAyKSArDQogIGdlb21fcG9pbnQoKQ0KDQojIHAgPC0gcCArDQojICAgc2NhbGVfY29sb3JfbWFudWFsKA0KIyAgICAgdmFsdWVzID0gYygNCiMgICAgICAgcGFsZXR0ZSRnZXQoInMzMCIpLCBwYWxldHRlJGdldCgiczMwIikNCiMgICAgICkNCiMgICApDQoNCnAgPC0gcCArDQogIHNjYWxlX3hfZGlzY3JldGUoDQogICAgbGFiZWxzID0gYygNCiAgICAgICJJbml0XG5UIiwgIkZpblxuVCINCiAgICApDQogICkNCg0KcA0KYGBgDQoNCg0KYGBge3J9DQojIEFOT1ZBIHVzaW5nIGFmZXggKGlkZW50aWNhbCB2YWx1ZXMgdG8gZXogYnV0IGV6IGRvZXNuJ3QgcmVtb3ZlIG1pc3Npbmcgcm93cykNCih0ZW1wX0FOT1ZBIDwtIGFvdl9jYXIobWVhbl90cmlhbF9zZXRfYW5nbGUgfiB0YXJnZXRBbmdsZSAqIHRyaWFsX3NldCArIEVycm9yKHBwaWQgLyAodGFyZ2V0QW5nbGUgKiB0cmlhbF9zZXQpKSwgZGF0YV9wcHQpKQ0KDQpiZiA8LSBhbm92YUJGKG1lYW5fdHJpYWxfc2V0X2FuZ2xlIH4gdGFyZ2V0QW5nbGUgKiB0cmlhbF9zZXQgKyBwcGlkLA0KICBkYXRhID0gZGF0YS5mcmFtZShkYXRhX3BwdCksIHdoaWNoUmFuZG9tID0gInBwaWQiLCBwcm9ncmVzcyA9IEZBTFNFDQopDQpwcmludChiZikNCmJheWVzZmFjdG9yX2luY2x1c2lvbihiZikNCmBgYA0KDQpObyBlZmZlY3RzIG9mIHRhcmdldCBBbmdsZSAoQkZpbmNsIG9mIDAuMDQgYW5kIDAuMDgpDQoNCiMgRHVhbCBMZWFybmluZyBFeHBlcmltZW50DQojIyBUcmFpbmluZyBQaGFzZSBUcmlhbCBTZXRzIC0gUmVhY2ggU3RlcA0KYGBge3J9DQpkcl8zMF9wcHRfdHJpYWxfc2V0cyA8LSBkcl8zMF9wcHRfdHJhaW5pbmcgJT4lDQogIGZpbHRlcih0cmlhbF9zZXQgPCA1KSAlPiUNCiAgZ3JvdXBfYnkocHBpZCwgdHJpYWxfc2V0LCB0YXJnZXRBbmdsZSkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBtZWFuX3RyaWFsX3NldF9hbmdsZSA9IG1lYW4odW5zaWduZWRfaGFuZF9hbmdsZSkNCiAgKQ0KDQpkcl8zMF9wcHRfdHJpYWxfc2V0cyRwcGlkIDwtIGFzLmZhY3Rvcihkcl8zMF9wcHRfdHJpYWxfc2V0cyRwcGlkKQ0KZHJfMzBfcHB0X3RyaWFsX3NldHMkdHJpYWxfc2V0IDwtIGFzLmZhY3Rvcihkcl8zMF9wcHRfdHJpYWxfc2V0cyR0cmlhbF9zZXQpDQpkcl8zMF9wcHRfdHJpYWxfc2V0cyR0YXJnZXRBbmdsZSA8LSBhcy5mYWN0b3IoZHJfMzBfcHB0X3RyaWFsX3NldHMkdGFyZ2V0QW5nbGUpDQoNCmRyXzMwX3RyaWFsX3NldF9kZXZzIDwtIGRyXzMwX3BwdF90cmlhbF9zZXRzICU+JQ0KICBncm91cF9ieSh0cmlhbF9zZXQsIHRhcmdldEFuZ2xlKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIHRyaWFsX3NldF9tZWFuID0gbWVhbihtZWFuX3RyaWFsX3NldF9hbmdsZSksDQogICAgdHJpYWxfc2V0X2NpID0gdmVjdG9yX2NvbmZpbnQobWVhbl90cmlhbF9zZXRfYW5nbGUpDQogICkNCg0KZGF0YV9wcHQgPC0gZHJfMzBfcHB0X3RyaWFsX3NldHMNCmRhdGFfdHJpYWxfc2V0IDwtIGRyXzMwX3RyaWFsX3NldF9kZXZzDQoNCiMgc2V0IHVwIHBsb3QNCnAgPC0gZGF0YV90cmlhbF9zZXQgJT4lDQogIGdncGxvdCgNCiAgICBhZXMoDQogICAgICB4ID0gdHJpYWxfc2V0LCB5ID0gdHJpYWxfc2V0X21lYW4sDQogICAgICBjb2xvciA9IHRyaWFsX3NldA0KICAgICkNCiAgKSArDQogIHRoZW1lX2NsYXNzaWMoKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKw0KICBsYWJzKA0KICAgIHggPSBOVUxMLA0KICAgIHkgPSAiSGFuZCBBbmdsZSAowrApIg0KICApDQoNCiMgYWRkIGhvcml6b250YWwgbGluZXMNCnAgPC0gcCArDQogIGdlb21faGxpbmUoDQogICAgeWludGVyY2VwdCA9IGMoLTMwLCAwLCAzMCksIGxpbmV3aWR0aCA9IDAuNCwNCiAgICBjb2xvdXIgPSAiI0NDQ0NDQyIsIGxpbmV0eXBlID0gInNvbGlkIg0KICApICsNCiAgZ2VvbV9obGluZSgNCiAgICB5aW50ZXJjZXB0ID0gYygtMTUsIDE1KSwgbGluZXdpZHRoID0gMC40LA0KICAgIGNvbG91ciA9ICIjQ0NDQ0NDIiwgbGluZXR5cGUgPSAiZGFzaGVkIg0KICApDQoNCiMgYWRkIGF4aXMgdGlja3MNCnAgPC0gcCArDQogIHNjYWxlX3lfY29udGludW91cygNCiAgICBsaW1pdHMgPSBjKC0zMCwgMzApLA0KICAgIGJyZWFrcyA9IGMoLTMwLCAtMTUsIDAsIDE1LCAzMCksDQogICAgbGFiZWxzID0gYygtMzAsIC0xNSwgMCwgMTUsIDMwKQ0KICApDQoNCiMgc2V0IGZvbnQgc2l6ZSB0byAxMQ0KcCA8LSBwICsNCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKQ0KDQojIGFkZCBkYXRhIHBvaW50cw0KcCA8LSBwICsNCiAgZ2VvbV9iZWVzd2FybSgNCiAgICBkYXRhID0gZGF0YV9wcHQsDQogICAgYWVzKHkgPSBtZWFuX3RyaWFsX3NldF9hbmdsZSwgY29sb3VyID0gdGFyZ2V0QW5nbGUpLA0KICAgIGFscGhhID0gMC41LA0KICAgIHNpemUgPSAxDQogICkgKw0KICBnZW9tX2xpbmVyYW5nZShhZXMoDQogICAgeW1pbiA9IHRyaWFsX3NldF9tZWFuIC0gdHJpYWxfc2V0X2NpLA0KICAgIHltYXggPSB0cmlhbF9zZXRfbWVhbiArIHRyaWFsX3NldF9jaQ0KICApLCBhbHBoYSA9IDAuMSwgbHdkID0gMikgKw0KICBnZW9tX3BvaW50KCkNCg0KIyBwIDwtIHAgKw0KIyAgIHNjYWxlX2NvbG9yX21hbnVhbCgNCiMgICAgIHZhbHVlcyA9IGMoDQojICAgICAgICIjNTU1NTU1IiwgIiM1NTU1NTUiDQojICAgICApDQojICAgKQ0KDQpwIDwtIHAgKw0KICBzY2FsZV94X2Rpc2NyZXRlKA0KICAgIGxhYmVscyA9IGMoDQogICAgICAiSW5pdCIsICJGaW4iDQogICAgKQ0KICApDQoNCnANCmBgYA0KDQpgYGB7cn0NCiMgQU5PVkEgdXNpbmcgYWZleCAoaWRlbnRpY2FsIHZhbHVlcyB0byBleiBidXQgZXogZG9lc24ndCByZW1vdmUgbWlzc2luZyByb3dzKQ0KKHRlbXBfQU5PVkEgPC0gYW92X2NhcihtZWFuX3RyaWFsX3NldF9hbmdsZSB+IHRhcmdldEFuZ2xlICogdHJpYWxfc2V0ICsgRXJyb3IocHBpZCAvICh0YXJnZXRBbmdsZSAqIHRyaWFsX3NldCkpLCBkYXRhX3BwdCkpDQoNCmJmIDwtIGFub3ZhQkYobWVhbl90cmlhbF9zZXRfYW5nbGUgfiB0YXJnZXRBbmdsZSAqIHRyaWFsX3NldCArIHBwaWQsDQogIGRhdGEgPSBkYXRhLmZyYW1lKGRhdGFfcHB0KSwgd2hpY2hSYW5kb20gPSAicHBpZCIsIHByb2dyZXNzID0gRkFMU0UNCikNCnByaW50KGJmKQ0KYmF5ZXNmYWN0b3JfaW5jbHVzaW9uKGJmKQ0KYGBgDQojIyBUcmFpbmluZyBQaGFzZSBUcmlhbCBTZXRzIC0gVHJhbnNwb3J0IFN0ZXANCmBgYHtyfQ0KZHJfMzBfcHB0X3RyaWFsX3NldHMgPC0gZHJfMzBfcHB0X3RyYWluaW5nICU+JQ0KICBmaWx0ZXIodHJpYWxfc2V0IDwgNSkgJT4lDQogIGdyb3VwX2J5KHBwaWQsIHRyaWFsX3NldCwgdGFyZ2V0QW5nbGUpICU+JQ0KICBzdW1tYXJpc2UoDQogICAgbWVhbl90cmlhbF9zZXRfYW5nbGUgPSBtZWFuKHVuc2lnbmVkX29ial9hbmdsZSkNCiAgKQ0KDQpkcl8zMF9wcHRfdHJpYWxfc2V0cyRwcGlkIDwtIGFzLmZhY3Rvcihkcl8zMF9wcHRfdHJpYWxfc2V0cyRwcGlkKQ0KZHJfMzBfcHB0X3RyaWFsX3NldHMkdHJpYWxfc2V0IDwtIGFzLmZhY3Rvcihkcl8zMF9wcHRfdHJpYWxfc2V0cyR0cmlhbF9zZXQpDQpkcl8zMF9wcHRfdHJpYWxfc2V0cyR0YXJnZXRBbmdsZSA8LSBhcy5mYWN0b3IoZHJfMzBfcHB0X3RyaWFsX3NldHMkdGFyZ2V0QW5nbGUpDQoNCmRyXzMwX3RyaWFsX3NldF9kZXZzIDwtIGRyXzMwX3BwdF90cmlhbF9zZXRzICU+JQ0KICBncm91cF9ieSh0cmlhbF9zZXQsIHRhcmdldEFuZ2xlKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIHRyaWFsX3NldF9tZWFuID0gbWVhbihtZWFuX3RyaWFsX3NldF9hbmdsZSksDQogICAgdHJpYWxfc2V0X2NpID0gdmVjdG9yX2NvbmZpbnQobWVhbl90cmlhbF9zZXRfYW5nbGUpDQogICkNCg0KZGF0YV9wcHQgPC0gZHJfMzBfcHB0X3RyaWFsX3NldHMNCmRhdGFfdHJpYWxfc2V0IDwtIGRyXzMwX3RyaWFsX3NldF9kZXZzDQoNCiMgc2V0IHVwIHBsb3QNCnAgPC0gZGF0YV90cmlhbF9zZXQgJT4lDQogIGdncGxvdCgNCiAgICBhZXMoDQogICAgICB4ID0gdHJpYWxfc2V0LCB5ID0gdHJpYWxfc2V0X21lYW4NCiAgICApDQogICkgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsNCiAgbGFicygNCiAgICB4ID0gTlVMTCwNCiAgICB5ID0gTlVMTA0KICApDQoNCiMgYWRkIGhvcml6b250YWwgbGluZXMNCnAgPC0gcCArDQogIGdlb21faGxpbmUoDQogICAgeWludGVyY2VwdCA9IGMoMCwgMzApLCBsaW5ld2lkdGggPSAwLjQsDQogICAgY29sb3VyID0gIiNDQ0NDQ0MiLCBsaW5ldHlwZSA9ICJzb2xpZCINCiAgKSArDQogIGdlb21faGxpbmUoDQogICAgeWludGVyY2VwdCA9IGMoMTUpLCBsaW5ld2lkdGggPSAwLjQsDQogICAgY29sb3VyID0gIiNDQ0NDQ0MiLCBsaW5ldHlwZSA9ICJkYXNoZWQiDQogICkNCg0KIyBhZGQgYXhpcyB0aWNrcw0KcCA8LSBwICsNCiAgc2NhbGVfeV9jb250aW51b3VzKA0KICAgIGxpbWl0cyA9IGMoLTE1LCA0MCksDQogICAgYnJlYWtzID0gYygwLCAxNSwgMzApLA0KICAgIGxhYmVscyA9IGMoMCwgMTUsIDMwKQ0KICApDQoNCiMgc2V0IGZvbnQgc2l6ZSB0byAxMQ0KcCA8LSBwICsNCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKQ0KDQojIGFkZCBkYXRhIHBvaW50cw0KcCA8LSBwICsNCiAgZ2VvbV9iZWVzd2FybSgNCiAgICBkYXRhID0gZGF0YV9wcHQsDQogICAgYWVzKHkgPSBtZWFuX3RyaWFsX3NldF9hbmdsZSwgY29sb3VyID0gdGFyZ2V0QW5nbGUpLA0KICAgIGFscGhhID0gMC41LA0KICAgIHNpemUgPSAxDQogICkgKw0KICBnZW9tX2xpbmVyYW5nZShhZXMoDQogICAgeW1pbiA9IHRyaWFsX3NldF9tZWFuIC0gdHJpYWxfc2V0X2NpLA0KICAgIHltYXggPSB0cmlhbF9zZXRfbWVhbiArIHRyaWFsX3NldF9jaQ0KICApLCBhbHBoYSA9IDAuMSwgbHdkID0gMikgKw0KICBnZW9tX3BvaW50KCkNCg0KIyBwIDwtIHAgKw0KIyAgIHNjYWxlX2NvbG9yX21hbnVhbCgNCiMgICAgIHZhbHVlcyA9IGMoDQojICAgICAgIHBhbGV0dGUkZ2V0KCJzMzAiKSwgcGFsZXR0ZSRnZXQoInMzMCIpDQojICAgICApDQojICAgKQ0KDQpwIDwtIHAgKw0KICBzY2FsZV94X2Rpc2NyZXRlKA0KICAgIGxhYmVscyA9IGMoDQogICAgICAiSW5pdFxuVCIsICJGaW5cblQiDQogICAgKQ0KICApDQoNCnANCmBgYA0KDQoNCmBgYHtyfQ0KIyBBTk9WQSB1c2luZyBhZmV4IChpZGVudGljYWwgdmFsdWVzIHRvIGV6IGJ1dCBleiBkb2Vzbid0IHJlbW92ZSBtaXNzaW5nIHJvd3MpDQoodGVtcF9BTk9WQSA8LSBhb3ZfY2FyKG1lYW5fdHJpYWxfc2V0X2FuZ2xlIH4gdGFyZ2V0QW5nbGUgKiB0cmlhbF9zZXQgKyBFcnJvcihwcGlkIC8gKHRhcmdldEFuZ2xlICogdHJpYWxfc2V0KSksIGRhdGFfcHB0KSkNCg0KYmYgPC0gYW5vdmFCRihtZWFuX3RyaWFsX3NldF9hbmdsZSB+IHRhcmdldEFuZ2xlICogdHJpYWxfc2V0ICsgcHBpZCwNCiAgZGF0YSA9IGRhdGEuZnJhbWUoZGF0YV9wcHQpLCB3aGljaFJhbmRvbSA9ICJwcGlkIiwgcHJvZ3Jlc3MgPSBGQUxTRQ0KKQ0KcHJpbnQoYmYpDQpiYXllc2ZhY3Rvcl9pbmNsdXNpb24oYmYpDQpgYGANCg0KDQpObyBlZmZlY3Qgb2YgdGFyZ2V0IGFuZ2xlIChCRmluYyA9IDAuMDcsIDAuMTQpDQoNCg0KIyMgQ2xhbXBlZCBUYXNrcw0KIyMjIE5vdCBleGNsdWRpbmcgc3RyYXRlZ3kNCmBgYHtyfQ0KZHJfMzBfcHB0X2luY2xfY2xhbXBlZCA8LSBkcl8zMF9pbmNsX2NsYW1wICU+JQ0KICBncm91cF9ieShwcGlkLCBvYmpfc2hhcGVfc2lnbiwgdGFyZ2V0QW5nbGUpICU+JQ0KICBzdW1tYXJpc2UoDQogICAgcHB0X21lYW5fYW5nbGUgPSBtZWFuKG9ial9hbmdsZV8zY21fbW92ZSksDQogICAgcHB0X2NpX2FuZ2xlID0gdmVjdG9yX2NvbmZpbnQob2JqX2FuZ2xlXzNjbV9tb3ZlKQ0KICApDQoNCmRyXzMwX3BwdF9pbmNsX2NsYW1wZWQkcHBpZCA8LSBmYWN0b3IoZHJfMzBfcHB0X2luY2xfY2xhbXBlZCRwcGlkKQ0KZHJfMzBfcHB0X2luY2xfY2xhbXBlZCRvYmpfc2hhcGVfc2lnbiA8LSBmYWN0b3IoZHJfMzBfcHB0X2luY2xfY2xhbXBlZCRvYmpfc2hhcGVfc2lnbikNCmRyXzMwX3BwdF9pbmNsX2NsYW1wZWQkdGFyZ2V0QW5nbGUgPC0gZmFjdG9yKGRyXzMwX3BwdF9pbmNsX2NsYW1wZWQkdGFyZ2V0QW5nbGUpDQoNCmRyXzMwX2V4cF9pbmNsX2NsYW1wZWQgPC0gZHJfMzBfcHB0X2luY2xfY2xhbXBlZCAlPiUNCiAgZ3JvdXBfYnkob2JqX3NoYXBlX3NpZ24sIHRhcmdldEFuZ2xlKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIG1lYW5fYW5nbGUgPSBtZWFuKHBwdF9tZWFuX2FuZ2xlKSwNCiAgICBjaV9hbmdsZSA9IHZlY3Rvcl9jb25maW50KHBwdF9tZWFuX2FuZ2xlKQ0KICApDQoNCmRhdGFfcHB0IDwtIGRyXzMwX3BwdF9pbmNsX2NsYW1wZWQNCmRhdGFfZXhwIDwtIGRyXzMwX2V4cF9pbmNsX2NsYW1wZWQNCg0KIyBzZXQgdXAgcGxvdA0KcCA8LSBkYXRhX2V4cCAlPiUNCiAgZ2dwbG90KA0KICAgIGFlcygNCiAgICAgIHggPSBvYmpfc2hhcGVfc2lnbiwNCiAgICAgIHkgPSBtZWFuX2FuZ2xlLA0KICAgICAgY29sb3IgPSBvYmpfc2hhcGVfc2lnbiwNCiAgICAgIHNoYXBlID0gdGFyZ2V0QW5nbGUNCiAgICApDQogICkgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsNCiAgbGFicygNCiAgICB4ID0gTlVMTCwNCiAgICB5ID0gTlVMTA0KICApDQoNCiMgYWRkIGhvcml6b250YWwgbGluZXMNCnAgPC0gcCArDQogIGdlb21faGxpbmUoDQogICAgeWludGVyY2VwdCA9IGMoLTMwLCAwLCAzMCksIGxpbmV3aWR0aCA9IDAuNCwNCiAgICBjb2xvdXIgPSAiI0NDQ0NDQyIsIGxpbmV0eXBlID0gInNvbGlkIg0KICApICsNCiAgZ2VvbV9obGluZSgNCiAgICB5aW50ZXJjZXB0ID0gYygtMTUsIDE1KSwgbGluZXdpZHRoID0gMC40LA0KICAgIGNvbG91ciA9ICIjQ0NDQ0NDIiwgbGluZXR5cGUgPSAiZGFzaGVkIg0KICApDQoNCiMgYWRkIGF4aXMgdGlja3MNCnAgPC0gcCArDQogIHNjYWxlX3lfY29udGludW91cygNCiAgICBsaW1pdHMgPSBjKC0zMCwgMzApLA0KICAgIGJyZWFrcyA9IGMoLTMwLCAtMTUsIDAsIDE1LCAzMCksDQogICAgbGFiZWxzID0gYygtMzAsIC0xNSwgMCwgMTUsIDMwKQ0KICApDQoNCnAgPC0gcCArDQogIHNjYWxlX3hfZGlzY3JldGUoDQogICAgbGFiZWxzID0gYygNCiAgICAgICJDVyIsICJDQ1ciDQogICAgKQ0KICApDQoNCiMgc2V0IGZvbnQgc2l6ZSB0byAxMQ0KcCA8LSBwICsNCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKQ0KDQojIGFkZCBkYXRhIHBvaW50cw0KcCA8LSBwICsNCiAgZ2VvbV9iZWVzd2FybSgNCiAgICBkYXRhID0gZGF0YV9wcHQsDQogICAgYWVzKA0KICAgICAgeCA9IG9ial9zaGFwZV9zaWduLA0KICAgICAgeSA9IHBwdF9tZWFuX2FuZ2xlLA0KICAgICAgY29sb3IgPSBvYmpfc2hhcGVfc2lnbiwNCiAgICAgIHNoYXBlID0gdGFyZ2V0QW5nbGUNCiAgICApLA0KICAgIHNpemUgPSAxLA0KICAgIGFscGhhID0gMC4yDQogICkgKw0KICBnZW9tX2xpbmVyYW5nZSgNCiAgICBhZXMoDQogICAgICB5bWluID0gbWVhbl9hbmdsZSAtIGNpX2FuZ2xlLA0KICAgICAgeW1heCA9IG1lYW5fYW5nbGUgKyBjaV9hbmdsZQ0KICAgICksDQogICAgYWxwaGEgPSAwLjUsIGx3ZCA9IDINCiAgKSArDQogIGdlb21fcG9pbnQoKQ0KDQpwIDwtIHAgKw0KICBzY2FsZV9jb2xvcl9tYW51YWwoDQogICAgdmFsdWVzID0gYyhwYWxldHRlJGdldCgiYS0xIiksIHBhbGV0dGUkZ2V0KCJhLTIiKSkNCiAgKQ0KDQpwDQpgYGANCg0KYGBge3J9DQojIHN1bW1hcnkgc3RhdGlzdGljcw0KZGF0YV9wcHQgJT4lDQogIGdyb3VwX2J5KG9ial9zaGFwZV9zaWduLCB0YXJnZXRBbmdsZSkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBtZWFuID0gbWVhbihwcHRfbWVhbl9hbmdsZSksDQogICAgY2kgPSB2ZWN0b3JfY29uZmludChwcHRfbWVhbl9hbmdsZSksDQogICAgbiA9IG4oKQ0KICApDQpgYGANCg0KYGBge3J9DQojIEFOT1ZBIHVzaW5nIGFmZXggKGlkZW50aWNhbCB2YWx1ZXMgdG8gZXogYnV0IGV6IGRvZXNuJ3QgcmVtb3ZlIG1pc3Npbmcgcm93cykNCih0ZW1wX0FOT1ZBIDwtIGFvdl9jYXIocHB0X21lYW5fYW5nbGUgfiB0YXJnZXRBbmdsZSAqIG9ial9zaGFwZV9zaWduICsgRXJyb3IocHBpZCAvICh0YXJnZXRBbmdsZSAqIG9ial9zaGFwZV9zaWduKSksIGRhdGFfcHB0KSkNCg0KYmYgPC0gYW5vdmFCRihwcHRfbWVhbl9hbmdsZSB+IHRhcmdldEFuZ2xlICogb2JqX3NoYXBlX3NpZ24gKyBwcGlkLA0KICBkYXRhID0gZGF0YS5mcmFtZShkYXRhX3BwdCksIHdoaWNoUmFuZG9tID0gInBwaWQiLCBwcm9ncmVzcyA9IEZBTFNFDQopDQpwcmludChiZikNCmJheWVzZmFjdG9yX2luY2x1c2lvbihiZikNCmBgYA0KDQoNCiMjIyBFeGNsdWRlIHN0cmF0ZWd5IHJlYWNoZXMNCmBgYHtyfQ0KZHJfMzBfcHB0X2V4Y2xfY2xhbXBlZCA8LSBkcl8zMF9leGNsX2NsYW1wICU+JQ0KICBncm91cF9ieShwcGlkLCBvYmpfc2hhcGVfc2lnbiwgdGFyZ2V0QW5nbGUpICU+JQ0KICBzdW1tYXJpc2UoDQogICAgcHB0X21lYW5fYW5nbGUgPSBtZWFuKG9ial9hbmdsZV8zY21fbW92ZSksDQogICAgcHB0X2NpX2FuZ2xlID0gdmVjdG9yX2NvbmZpbnQob2JqX2FuZ2xlXzNjbV9tb3ZlKQ0KICApDQoNCmRyXzMwX3BwdF9leGNsX2NsYW1wZWQkcHBpZCA8LSBmYWN0b3IoZHJfMzBfcHB0X2V4Y2xfY2xhbXBlZCRwcGlkKQ0KZHJfMzBfcHB0X2V4Y2xfY2xhbXBlZCRvYmpfc2hhcGVfc2lnbiA8LSBmYWN0b3IoZHJfMzBfcHB0X2V4Y2xfY2xhbXBlZCRvYmpfc2hhcGVfc2lnbikNCmRyXzMwX3BwdF9leGNsX2NsYW1wZWQkdGFyZ2V0QW5nbGUgPC0gZmFjdG9yKGRyXzMwX3BwdF9leGNsX2NsYW1wZWQkdGFyZ2V0QW5nbGUpDQoNCmRyXzMwX2V4cF9leGNsX2NsYW1wZWQgPC0gZHJfMzBfcHB0X2V4Y2xfY2xhbXBlZCAlPiUNCiAgZ3JvdXBfYnkob2JqX3NoYXBlX3NpZ24sIHRhcmdldEFuZ2xlKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIG1lYW5fYW5nbGUgPSBtZWFuKHBwdF9tZWFuX2FuZ2xlKSwNCiAgICBjaV9hbmdsZSA9IHZlY3Rvcl9jb25maW50KHBwdF9tZWFuX2FuZ2xlKQ0KICApDQoNCmRhdGFfcHB0IDwtIGRyXzMwX3BwdF9leGNsX2NsYW1wZWQNCmRhdGFfZXhwIDwtIGRyXzMwX2V4cF9leGNsX2NsYW1wZWQNCg0KIyBzZXQgdXAgcGxvdA0KcCA8LSBkYXRhX2V4cCAlPiUNCiAgZ2dwbG90KA0KICAgIGFlcygNCiAgICAgIHggPSBvYmpfc2hhcGVfc2lnbiwNCiAgICAgIHkgPSBtZWFuX2FuZ2xlLA0KICAgICAgY29sb3IgPSBvYmpfc2hhcGVfc2lnbiwNCiAgICAgIHNoYXBlID0gdGFyZ2V0QW5nbGUNCiAgICApDQogICkgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsNCiAgbGFicygNCiAgICB4ID0gTlVMTCwNCiAgICB5ID0gTlVMTA0KICApDQoNCiMgYWRkIGhvcml6b250YWwgbGluZXMNCnAgPC0gcCArDQogIGdlb21faGxpbmUoDQogICAgeWludGVyY2VwdCA9IGMoLTMwLCAwLCAzMCksIGxpbmV3aWR0aCA9IDAuNCwNCiAgICBjb2xvdXIgPSAiI0NDQ0NDQyIsIGxpbmV0eXBlID0gInNvbGlkIg0KICApICsNCiAgZ2VvbV9obGluZSgNCiAgICB5aW50ZXJjZXB0ID0gYygtMTUsIDE1KSwgbGluZXdpZHRoID0gMC40LA0KICAgIGNvbG91ciA9ICIjQ0NDQ0NDIiwgbGluZXR5cGUgPSAiZGFzaGVkIg0KICApDQoNCiMgYWRkIGF4aXMgdGlja3MNCnAgPC0gcCArDQogIHNjYWxlX3lfY29udGludW91cygNCiAgICBsaW1pdHMgPSBjKC0zMCwgMzApLA0KICAgIGJyZWFrcyA9IGMoLTMwLCAtMTUsIDAsIDE1LCAzMCksDQogICAgbGFiZWxzID0gYygtMzAsIC0xNSwgMCwgMTUsIDMwKQ0KICApDQoNCnAgPC0gcCArDQogIHNjYWxlX3hfZGlzY3JldGUoDQogICAgbGFiZWxzID0gYygNCiAgICAgICJDVyIsICJDQ1ciDQogICAgKQ0KICApDQoNCiMgc2V0IGZvbnQgc2l6ZSB0byAxMQ0KcCA8LSBwICsNCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKQ0KDQojIGFkZCBkYXRhIHBvaW50cw0KcCA8LSBwICsNCiAgZ2VvbV9iZWVzd2FybSgNCiAgICBkYXRhID0gZGF0YV9wcHQsDQogICAgYWVzKA0KICAgICAgeCA9IG9ial9zaGFwZV9zaWduLA0KICAgICAgeSA9IHBwdF9tZWFuX2FuZ2xlLA0KICAgICAgY29sb3IgPSBvYmpfc2hhcGVfc2lnbiwNCiAgICAgIHNoYXBlID0gdGFyZ2V0QW5nbGUNCiAgICApLA0KICAgIHNpemUgPSAxLA0KICAgIGFscGhhID0gMC4yDQogICkgKw0KICBnZW9tX2xpbmVyYW5nZSgNCiAgICBhZXMoDQogICAgICB5bWluID0gbWVhbl9hbmdsZSAtIGNpX2FuZ2xlLA0KICAgICAgeW1heCA9IG1lYW5fYW5nbGUgKyBjaV9hbmdsZQ0KICAgICksDQogICAgYWxwaGEgPSAwLjUsIGx3ZCA9IDINCiAgKSArDQogIGdlb21fcG9pbnQoKQ0KDQpwIDwtIHAgKw0KICBzY2FsZV9jb2xvcl9tYW51YWwoDQogICAgdmFsdWVzID0gYyhwYWxldHRlJGdldCgiYS0xIiksIHBhbGV0dGUkZ2V0KCJhLTIiKSkNCiAgKQ0KDQpwDQpgYGANCg0KYGBge3J9DQojIHN1bW1hcnkgc3RhdGlzdGljcw0KZGF0YV9wcHQgJT4lDQogIGdyb3VwX2J5KG9ial9zaGFwZV9zaWduLCB0YXJnZXRBbmdsZSkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBtZWFuID0gbWVhbihwcHRfbWVhbl9hbmdsZSksDQogICAgY2kgPSB2ZWN0b3JfY29uZmludChwcHRfbWVhbl9hbmdsZSksDQogICAgbiA9IG4oKQ0KICApDQpgYGANCg0KYGBge3J9DQojIEFOT1ZBIHVzaW5nIGFmZXggKGlkZW50aWNhbCB2YWx1ZXMgdG8gZXogYnV0IGV6IGRvZXNuJ3QgcmVtb3ZlIG1pc3Npbmcgcm93cykNCih0ZW1wX0FOT1ZBIDwtIGFvdl9jYXIocHB0X21lYW5fYW5nbGUgfiB0YXJnZXRBbmdsZSAqIG9ial9zaGFwZV9zaWduICsgRXJyb3IocHBpZCAvICh0YXJnZXRBbmdsZSAqIG9ial9zaGFwZV9zaWduKSksIGRhdGFfcHB0KSkNCg0KYmYgPC0gYW5vdmFCRihwcHRfbWVhbl9hbmdsZSB+IHRhcmdldEFuZ2xlICogb2JqX3NoYXBlX3NpZ24gKyBwcGlkLA0KICBkYXRhID0gZGF0YS5mcmFtZShkYXRhX3BwdCksIHdoaWNoUmFuZG9tID0gInBwaWQiLCBwcm9ncmVzcyA9IEZBTFNFDQopDQpwcmludChiZikNCmJheWVzZmFjdG9yX2luY2x1c2lvbihiZikNCmBgYA0KYGBge3J9DQojIHBvc3Rob2MgdGVzdHMNCihtMSA8LSBlbW1lYW5zKHRlbXBfQU5PVkEsIH4gdGFyZ2V0QW5nbGUgKiBvYmpfc2hhcGVfc2lnbikpDQpwYWlycyhtMSkNCmBgYA0KDQojIEhhbmQgUm90YXRpb25zDQpgYGB7cn0NCiMgaGVscGVyIGZ1bmN0aW9uDQphdmVyYWdlX2NpcmNsZSA8LSBmdW5jdGlvbihudW1fdmVjKSB7DQogICMgQ29udmVydCB2ZWN0b3JzIHRvIHJhZGlhbnMNCiAgdmVjdG9yc19yYWQgPC0gbGFwcGx5KG51bV92ZWMsIGZ1bmN0aW9uKHYpIHJhZCh2KSkNCg0KICAjIENhbGN1bGF0ZSBhdmVyYWdlIGZvciBlYWNoIGRpbWVuc2lvbg0KICBjaXJjdWxhcl9tZWFuIDwtIG1lYW4oY2lyY3VsYXIodmVjdG9yc19yYWQpLCBuYS5ybSA9IFRSVUUpDQoNCiAgIyBDb252ZXJ0IHRoZSBhdmVyYWdlIHZlY3RvciBiYWNrIHRvIGRlZ3JlZXMNCiAgZGVnKGNpcmN1bGFyX21lYW4pDQp9DQoNCiMgaXNvbGF0ZSBhbGwgdHJpYWxzIHdoZXJlIGJhc2VsaW5lX2Jsb2NrIGlzIFRSVUUNCmRyXzMwX2Jhc2VsaW5lIDwtIGRyXzMwX2FsbCAlPiUNCiAgZmlsdGVyKGJhc2VsaW5lX2Jsb2NrID09IFRSVUUpDQoNCiMgbWFrZSBwcGlkLCBvYmpfc2hhcGUsIHRhcmdldEFuZ2xlIGZhY3RvcnMNCmRyXzMwX2Jhc2VsaW5lJHBwaWQgPC0gZmFjdG9yKGRyXzMwX2Jhc2VsaW5lJHBwaWQpDQpkcl8zMF9iYXNlbGluZSRvYmpfc2hhcGUgPC0gZmFjdG9yKGRyXzMwX2Jhc2VsaW5lJG9ial9zaGFwZSkNCmRyXzMwX2Jhc2VsaW5lJHRhcmdldEFuZ2xlIDwtIGZhY3Rvcihkcl8zMF9iYXNlbGluZSR0YXJnZXRBbmdsZSkNCg0Kcm90X2F0X3BpY2t1cF9zdW1tYXJ5IDwtIGRyXzMwX2Jhc2VsaW5lICU+JQ0KICBncm91cF9ieShwcGlkLCBvYmpfc2hhcGUsIHRhcmdldEFuZ2xlKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIG4oKQ0KICApDQoNCiMgYWRkIGVtcHR5IGNvbHVtbnMNCnJvdF9hdF9waWNrdXBfc3VtbWFyeSRtZWFuX3JvdF94X2F0X3BpY2t1cCA8LSBOQQ0Kcm90X2F0X3BpY2t1cF9zdW1tYXJ5JGNpX3JvdF94X2F0X3BpY2t1cCA8LSBOQQ0Kcm90X2F0X3BpY2t1cF9zdW1tYXJ5JG1lYW5fcm90X3lfYXRfcGlja3VwIDwtIE5BDQpyb3RfYXRfcGlja3VwX3N1bW1hcnkkY2lfcm90X3lfYXRfcGlja3VwIDwtIE5BDQpyb3RfYXRfcGlja3VwX3N1bW1hcnkkbWVhbl9yb3Rfel9hdF9waWNrdXAgPC0gTkENCnJvdF9hdF9waWNrdXBfc3VtbWFyeSRjaV9yb3Rfel9hdF9waWNrdXAgPC0gTkENCg0KIyBsb29wIHRocm91Z2ggcm93cyBvZiByb3RfYXRfcGlja3VwX3N1bW1hcnkgYW5kIGNhbGN1bGF0ZSBhdmVyYWdlIHJvdGF0aW9uDQpmb3IgKGkgaW4gMTpucm93KHJvdF9hdF9waWNrdXBfc3VtbWFyeSkpIHsNCiAgIyBnZXQgcHBpZCwgb2JqX3NoYXBlLCB0YXJnZXRBbmdsZQ0KICByb3dfcHBpZCA8LSByb3RfYXRfcGlja3VwX3N1bW1hcnkkcHBpZFtpXQ0KICByb3dfb2JqX3NoYXBlIDwtIHJvdF9hdF9waWNrdXBfc3VtbWFyeSRvYmpfc2hhcGVbaV0NCiAgcm93X3RhcmdldEFuZ2xlIDwtIHJvdF9hdF9waWNrdXBfc3VtbWFyeSR0YXJnZXRBbmdsZVtpXQ0KDQogICMgZ2V0IGFsbCByb3dzIGZvciB0aGlzIHBwaWQsIG9ial9zaGFwZSwgdGFyZ2V0QW5nbGUNCiAgdGVtcF9kYXRhIDwtIGRyXzMwX2Jhc2VsaW5lICU+JQ0KICAgIGZpbHRlcihwcGlkID09IHJvd19wcGlkLCBvYmpfc2hhcGUgPT0gcm93X29ial9zaGFwZSwgdGFyZ2V0QW5nbGUgPT0gcm93X3RhcmdldEFuZ2xlKQ0KDQogICMgZ2V0IGFsbCBoYW5kX3JvdF94X2F0X3BpY2t1cCB2YWx1ZXMNCiAgcm90X3ggPC0gdGVtcF9kYXRhJGhhbmRfcm90X3hfYXRfcGlja3VwDQoNCiAgIyBnZXQgYWxsIGhhbmRfcm90X3lfYXRfcGlja3VwIHZhbHVlcw0KICByb3RfeSA8LSB0ZW1wX2RhdGEkaGFuZF9yb3RfeV9hdF9waWNrdXANCg0KICAjIGdldCBhbGwgaGFuZF9yb3Rfel9hdF9waWNrdXAgdmFsdWVzDQogIHJvdF96IDwtIHRlbXBfZGF0YSRoYW5kX3JvdF96X2F0X3BpY2t1cA0KDQogICMgYWRkIHRvIHJvdF9hdF9waWNrdXBfc3VtbWFyeQ0KICByb3RfYXRfcGlja3VwX3N1bW1hcnkkbWVhbl9yb3RfeF9hdF9waWNrdXBbaV0gPC0gYXZlcmFnZV9jaXJjbGUocm90X3gpDQogIHJvdF9hdF9waWNrdXBfc3VtbWFyeSRjaV9yb3RfeF9hdF9waWNrdXBbaV0gPC0gdmVjdG9yX2NvbmZpbnQocm90X3gpDQogIHJvdF9hdF9waWNrdXBfc3VtbWFyeSRtZWFuX3JvdF95X2F0X3BpY2t1cFtpXSA8LSBhdmVyYWdlX2NpcmNsZShyb3RfeSkNCiAgcm90X2F0X3BpY2t1cF9zdW1tYXJ5JGNpX3JvdF95X2F0X3BpY2t1cFtpXSA8LSB2ZWN0b3JfY29uZmludChyb3RfeSkNCiAgcm90X2F0X3BpY2t1cF9zdW1tYXJ5JG1lYW5fcm90X3pfYXRfcGlja3VwW2ldIDwtIGF2ZXJhZ2VfY2lyY2xlKHJvdF96KQ0KICByb3RfYXRfcGlja3VwX3N1bW1hcnkkY2lfcm90X3pfYXRfcGlja3VwW2ldIDwtIHZlY3Rvcl9jb25maW50KHJvdF96KQ0KfQ0KDQojIHN1bW1hcml6ZQ0Kcm90X2F0X3BpY2t1cF9zdW1tYXJ5MiA8LSByb3RfYXRfcGlja3VwX3N1bW1hcnkgJT4lDQogIGdyb3VwX2J5KG9ial9zaGFwZSwgdGFyZ2V0QW5nbGUpICU+JQ0KICBzdW1tYXJpc2UoDQogICAgbWVhbl9yb3RfeF9hdF9waWNrdXAyID0gbWVhbihtZWFuX3JvdF94X2F0X3BpY2t1cCksDQogICAgY2lfcm90X3hfYXRfcGlja3VwMiA9IHZlY3Rvcl9jb25maW50KG1lYW5fcm90X3hfYXRfcGlja3VwKSwNCiAgICBtZWFuX3JvdF95X2F0X3BpY2t1cDIgPSBtZWFuKG1lYW5fcm90X3lfYXRfcGlja3VwKSwNCiAgICBjaV9yb3RfeV9hdF9waWNrdXAyID0gdmVjdG9yX2NvbmZpbnQobWVhbl9yb3RfeV9hdF9waWNrdXApLA0KICAgIG1lYW5fcm90X3pfYXRfcGlja3VwMiA9IG1lYW4obWVhbl9yb3Rfel9hdF9waWNrdXApLA0KICAgIGNpX3JvdF96X2F0X3BpY2t1cDIgPSB2ZWN0b3JfY29uZmludChtZWFuX3JvdF96X2F0X3BpY2t1cCkNCiAgKQ0KYGBgDQoNCmBgYHtyfQ0KIyBzZXQgdXAgcGxvdA0KcCA8LSByb3RfYXRfcGlja3VwX3N1bW1hcnkgJT4lDQogIGdncGxvdCgNCiAgICBhZXMoDQogICAgICB4ID0gb2JqX3NoYXBlLA0KICAgICAgeSA9IG1lYW5fcm90X3hfYXRfcGlja3VwLA0KICAgICAgY29sb3IgPSB0YXJnZXRBbmdsZQ0KICAgICkNCiAgKSArDQogIHRoZW1lX2NsYXNzaWMoKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKw0KICBsYWJzKA0KICAgIHggPSBOVUxMLA0KICAgIHkgPSBOVUxMDQogICkgKw0KICAjIGFkZCBkYXRhIHBvaW50cw0KICBnZW9tX2JlZXN3YXJtKA0KICAgIGFlcygNCiAgICAgIHggPSBvYmpfc2hhcGUsDQogICAgICB5ID0gbWVhbl9yb3RfeF9hdF9waWNrdXAsDQogICAgICBjb2xvciA9IHRhcmdldEFuZ2xlDQogICAgKSwNCiAgICBzaXplID0gMSwNCiAgICBhbHBoYSA9IDAuMg0KICApICsNCiAgZ2VvbV9saW5lcmFuZ2UoDQogICAgZGF0YSA9IHJvdF9hdF9waWNrdXBfc3VtbWFyeTIsDQogICAgYWVzKA0KICAgICAgeSA9IG1lYW5fcm90X3hfYXRfcGlja3VwMiwNCiAgICAgIHltaW4gPSBtZWFuX3JvdF94X2F0X3BpY2t1cDIgLSBjaV9yb3RfeF9hdF9waWNrdXAyLA0KICAgICAgeW1heCA9IG1lYW5fcm90X3hfYXRfcGlja3VwMiArIGNpX3JvdF94X2F0X3BpY2t1cDINCiAgICApLA0KICAgIGFscGhhID0gMC41LCBsd2QgPSAyDQogICkgKw0KICBnZW9tX3BvaW50KA0KICAgIGRhdGEgPSByb3RfYXRfcGlja3VwX3N1bW1hcnkyLA0KICAgIGFlcygNCiAgICAgIHggPSBvYmpfc2hhcGUsDQogICAgICB5ID0gbWVhbl9yb3RfeF9hdF9waWNrdXAyLA0KICAgICAgY29sb3IgPSB0YXJnZXRBbmdsZQ0KICAgICkNCiAgKQ0KDQojIHNhbWUgYXMgYWJvdmUgYnV0IGFkZCB5IGluIGEgZGlmZmVyZW50IHBsb3QNCnEgPC0gcm90X2F0X3BpY2t1cF9zdW1tYXJ5ICU+JQ0KICBnZ3Bsb3QoDQogICAgYWVzKA0KICAgICAgeCA9IG9ial9zaGFwZSwNCiAgICAgIHkgPSBtZWFuX3JvdF95X2F0X3BpY2t1cCwNCiAgICAgIGNvbG9yID0gdGFyZ2V0QW5nbGUNCiAgICApDQogICkgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsNCiAgbGFicygNCiAgICB4ID0gTlVMTCwNCiAgICB5ID0gTlVMTA0KICApICsNCiAgIyBhZGQgZGF0YSBwb2ludHMNCiAgZ2VvbV9iZWVzd2FybSgNCiAgICBhZXMoDQogICAgICB4ID0gb2JqX3NoYXBlLA0KICAgICAgeSA9IG1lYW5fcm90X3lfYXRfcGlja3VwLA0KICAgICAgY29sb3IgPSB0YXJnZXRBbmdsZQ0KICAgICksDQogICAgc2l6ZSA9IDEsDQogICAgYWxwaGEgPSAwLjINCiAgKSArDQogIGdlb21fbGluZXJhbmdlKA0KICAgIGRhdGEgPSByb3RfYXRfcGlja3VwX3N1bW1hcnkyLA0KICAgIGFlcygNCiAgICAgIHkgPSBtZWFuX3JvdF95X2F0X3BpY2t1cDIsDQogICAgICB5bWluID0gbWVhbl9yb3RfeV9hdF9waWNrdXAyIC0gY2lfcm90X3lfYXRfcGlja3VwMiwNCiAgICAgIHltYXggPSBtZWFuX3JvdF95X2F0X3BpY2t1cDIgKyBjaV9yb3RfeV9hdF9waWNrdXAyDQogICAgKSwNCiAgICBhbHBoYSA9IDAuNSwgbHdkID0gMg0KICApICsNCiAgZ2VvbV9wb2ludCgNCiAgICBkYXRhID0gcm90X2F0X3BpY2t1cF9zdW1tYXJ5MiwNCiAgICBhZXMoDQogICAgICB4ID0gb2JqX3NoYXBlLA0KICAgICAgeSA9IG1lYW5fcm90X3lfYXRfcGlja3VwMiwNCiAgICAgIGNvbG9yID0gdGFyZ2V0QW5nbGUNCiAgICApDQogICkNCg0KIyBzYW1lIGFzIGFib3ZlIGJ1dCBhZGQgeiBpbiBhIGRpZmZlcmVudCBwbG90DQpyIDwtIHJvdF9hdF9waWNrdXBfc3VtbWFyeSAlPiUNCiAgZ2dwbG90KA0KICAgIGFlcygNCiAgICAgIHggPSBvYmpfc2hhcGUsDQogICAgICB5ID0gbWVhbl9yb3Rfel9hdF9waWNrdXAsDQogICAgICBjb2xvciA9IHRhcmdldEFuZ2xlDQogICAgKQ0KICApICsNCiAgdGhlbWVfY2xhc3NpYygpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArDQogIGxhYnMoDQogICAgeCA9IE5VTEwsDQogICAgeSA9IE5VTEwNCiAgKSArDQogICMgYWRkIGRhdGEgcG9pbnRzDQogIGdlb21fYmVlc3dhcm0oDQogICAgYWVzKA0KICAgICAgeCA9IG9ial9zaGFwZSwNCiAgICAgIHkgPSBtZWFuX3JvdF96X2F0X3BpY2t1cCwNCiAgICAgIGNvbG9yID0gdGFyZ2V0QW5nbGUNCiAgICApLA0KICAgIHNpemUgPSAxLA0KICAgIGFscGhhID0gMC4yDQogICkgKw0KICBnZW9tX2xpbmVyYW5nZSgNCiAgICBkYXRhID0gcm90X2F0X3BpY2t1cF9zdW1tYXJ5MiwNCiAgICBhZXMoDQogICAgICB5ID0gbWVhbl9yb3Rfel9hdF9waWNrdXAyLA0KICAgICAgeW1pbiA9IG1lYW5fcm90X3pfYXRfcGlja3VwMiAtIGNpX3JvdF96X2F0X3BpY2t1cDIsDQogICAgICB5bWF4ID0gbWVhbl9yb3Rfel9hdF9waWNrdXAyICsgY2lfcm90X3pfYXRfcGlja3VwMg0KICAgICksDQogICAgYWxwaGEgPSAwLjUsIGx3ZCA9IDINCiAgKSArDQogIGdlb21fcG9pbnQoDQogICAgZGF0YSA9IHJvdF9hdF9waWNrdXBfc3VtbWFyeTIsDQogICAgYWVzKA0KICAgICAgeCA9IG9ial9zaGFwZSwNCiAgICAgIHkgPSBtZWFuX3JvdF96X2F0X3BpY2t1cDIsDQogICAgICBjb2xvciA9IHRhcmdldEFuZ2xlDQogICAgKQ0KICApDQoNCiMgcGxvdHMNCnANCnENCnINCmBgYA0KYGBge3J9DQojIEFOT1ZBIHVzaW5nIGFmZXggKGlkZW50aWNhbCB2YWx1ZXMgdG8gZXogYnV0IGV6IGRvZXNuJ3QgcmVtb3ZlIG1pc3Npbmcgcm93cykNCih0ZW1wX0FOT1ZBIDwtIGFvdl9jYXIobWVhbl9yb3RfeF9hdF9waWNrdXAgfiBvYmpfc2hhcGUgKiB0YXJnZXRBbmdsZSArIEVycm9yKHBwaWQgLyAob2JqX3NoYXBlICogdGFyZ2V0QW5nbGUpKSwgcm90X2F0X3BpY2t1cF9zdW1tYXJ5KSkNCg0KYmYgPC0gYW5vdmFCRihtZWFuX3JvdF94X2F0X3BpY2t1cCB+IG9ial9zaGFwZSAqIHRhcmdldEFuZ2xlICsgcHBpZCwNCiAgZGF0YSA9IGRhdGEuZnJhbWUocm90X2F0X3BpY2t1cF9zdW1tYXJ5KSwgd2hpY2hSYW5kb20gPSAicHBpZCIsIHByb2dyZXNzID0gRkFMU0UNCikNCnByaW50KGJmKQ0KYmF5ZXNmYWN0b3JfaW5jbHVzaW9uKGJmKQ0KDQojIHBvc3Rob2MgdGVzdHMNCihtMSA8LSBlbW1lYW5zKHRlbXBfQU5PVkEsIH4gb2JqX3NoYXBlICogdGFyZ2V0QW5nbGUpKQ0KcGFpcnMobTEpDQpgYGANCg0KDQpgYGB7cn0NCiMgRmluDQpgYGANCg0K